Functions

In kaoscript, there is three types of functions:

  • named functions
  • anonymous functions
  • arrow functions
new thisshared thisoverload-ableasync-ablereturn typeerror typesstatementexpression
named functionYESYESYESYESYESYES
anonymous functionYESYESYESYESYES
arrow functionYESYESYESYESYES

An arrow function shares the same this as its caller.

named function

Syntax

[async] func varname([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] [ => expression | {
...statements
}]

Examples

import '@zokugun/lang'
func alpha(n: Number, percentage = false): Number {
const i = n.toInt()
return 1 if i == NaN else (percentage ? i / 100 : i).limit(0, 1).round(3)
}
func red() => '#FF0000'

anonymous function

Syntax

[async] func([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] [ => expression | {
...statements
}]

Examples

foobar(func(a:Number, b:Number) {
return a - b
})
foobar(func(a:Number, b:Number): Number => a - b)

arrow function

Syntax

[async] [([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] | parameter ] => [ expression | {
...statements
}]

Examples

const foo = (a:Number, b:Number) => a - b
let four = (a => a / 10)(42)

parameters

Syntax

[varname | destructuring | ...[varname]] [!] [: type] [?] [= expression]

Examples

require expect: func
func foo(u = null, v, x, y = null, z = null) {
return [u, v, x, y, z]
}
expect(() => foo()).to.throw()
expect(() => foo(1)).to.throw()
expect(foo(1, 2)).to.eql([null, 1, 2, null, null])
expect(foo(1, 2, 3)).to.eql([1, 2, 3, null, null])
expect(foo(1, 2, 3, 4)).to.eql([1, 2, 3, 4, null])
expect(foo(1, 2, 3, 4, 5)).to.eql([1, 2, 3, 4, 5])

Distribution

RequiredNullableTypedDefault Value
foo(x)YES
foo(x?)YESYES
foo(x = null)YESYES
foo(x = 'foobar')YES
foo(x? = 'foobar')YESYES
foo(x! = null)YESYESYES
foo(x! = 'foobar')YESYES
foo(x!? = 'foobar')YESYESYES
foo(x: String)YESYES
foo(x: String?)YESYESYES
foo(x: String = null)YESYESYES
foo(x: String = 'foobar')YESYES
foo(x: String? = null)YESYESYES
foo(x: String? = 'foobar')YESYESYES
foo(x!: String = null)YESYESYESYES
foo(x!: String = 'foobar')YESYESYES
foo(x!: String? = null)YESYESYESYES
foo(x!: String? = 'foobar')YESYESYESYES

rest parameter

Unlike JavaScript, in kaoscript, the rest parameter is allowed in any position.

Examples

func foo(...items) {
console.log(items)
}
func quux(x = 1, ...items, z = 1) {
console.log(x, items, z)
}
func corge(...items = [1..5]) {
console.log(items)
}

Arity

The rest parameter can have arity like:

func foo(...{1,3}args) {
// args will contain between 1 and 3 elements
}
func bar(...{3,}args) {
// args will contain at least 3 elements
}
func quux(...{,3}args) {
// args will contain at most 3 elements
}
func corge(...{3}args) {
// args will contain 3 elements
}

anonymous parameter

In kaoscript, a parameter can be ignored.

Examples

func foo(...) {
}
func bar(, x, y) {
console.log(x, y)
}

asynchronous

async/await use the traditional callback(error, ...values) where the error can be catched with try/catch.

Examples

import '@zokugun/lang'
import 'child_process' for exec
const df_regex = /([\/[a-z0-9\-\_\s]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+%)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+%)\s+(\/.*)/i
async func disks() {
const stdout: string, stderr = await exec('df -k')
const disks = []
for const line in stdout.lines() {
if const matches = df_regex.exec(line) {
disks.push({
device: matches[1].trim(),
mount: matches[9],
total: matches[2].toInt() * 1024,
used: matches[3].toInt() * 1024,
available: matches[4].toInt() * 1024
})
}
}
return disks
}
let d = await disks()

error handling

Like Java, in kaoscript, a function exposes the list of possible errors. Those errors will have to be handled by the caller. (This behaviour can be disabled with an attribute.)

Examples

func foobar() ~ Error {
}
func handled() {
try {
foobar()
}
}
func passed() ~ Error {
foobar()
}
#[error(off)]
func disabled() {
foobar()
}
#[error(ignore(Error))]
func filtered() {
foobar()
}

overloading

kaoscript allows named functions to be overloaded.

Examples

func reverse(value: String): String => value.split('').reverse().join('')
func reverse(value: Array): Array => value.slice().reverse()
reverse('foobar')
// 'raboof'
reverse([1, 2, 3, 4])
// [4, 3, 2, 1]

currying

this is
^$first argument
^^null
^@function's this

argument

const log = console.log^$(console, 'hello:')
log('foo')
// hello: foo

null

func log(...args) {
console.log(...args)
}
const logHello = log^^('hello:')
logHello('foo')
// hello: foo

self

const log = console.log^@('hello:')
log('foo')
// hello: foo

calling

this is
*$first argument
**null

argument

func log(...args) {
this.log(...args)
}
log*$(console, 'hello')

null

func log(...args) {
console.log(...args)
}
log**('hello')