In kaoscript, there is three types of functions:
new this | shared this | overload-able | async-able | return type | error types | statement | expression | |
---|---|---|---|---|---|---|---|---|
named function | YES | YES | YES | YES | YES | YES | ||
anonymous function | YES | YES | YES | YES | YES | |||
arrow function | YES | YES | YES | YES | YES |
An arrow function shares the same this
as its caller.
[async] func varname([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] [ => expression | {
...statements
}]
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'
[async] func([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] [ => expression | {
...statements
}]
foobar(func(a:Number, b:Number) {
return a - b
})
foobar(func(a:Number, b:Number): Number => a - b)
[async] [([[parameter1] [, [parameter2] ... [, [parameterN]]])[: type] [~ class1 [, class2 ... [, classN]]] | parameter ] => [ expression | {
...statements
}]
const foo = (a:Number, b:Number) => a - b
let four = (a => a / 10)(42)
[varname | destructuring | ...[varname]] [!] [: type] [?] [= expression]
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])
Required | Nullable | Typed | Default Value | |
---|---|---|---|---|
foo(x) | YES | |||
foo(x?) | YES | YES | ||
foo(x = null) | YES | YES | ||
foo(x = 'foobar') | YES | |||
foo(x? = 'foobar') | YES | YES | ||
foo(x! = null) | YES | YES | YES | |
foo(x! = 'foobar') | YES | YES | ||
foo(x!? = 'foobar') | YES | YES | YES | |
foo(x: String) | YES | YES | ||
foo(x: String?) | YES | YES | YES | |
foo(x: String = null) | YES | YES | YES | |
foo(x: String = 'foobar') | YES | YES | ||
foo(x: String? = null) | YES | YES | YES | |
foo(x: String? = 'foobar') | YES | YES | YES | |
foo(x!: String = null) | YES | YES | YES | YES |
foo(x!: String = 'foobar') | YES | YES | YES | |
foo(x!: String? = null) | YES | YES | YES | YES |
foo(x!: String? = 'foobar') | YES | YES | YES | YES |
Unlike JavaScript, in kaoscript, the rest
parameter is allowed in any position.
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)
}
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
}
In kaoscript, a parameter can be ignored.
func foo(...) {
}
func bar(, x, y) {
console.log(x, y)
}
async/await
use the traditional callback(error, ...values)
where the error
can be catched with try/catch
.
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()
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.)
func foobar() ~ Error {
}
func handled() {
try {
foobar()
}
}
func passed() ~ Error {
foobar()
}
#[error(off)]
func disabled() {
foobar()
}
#[error(ignore(Error))]
func filtered() {
foobar()
}
kaoscript allows named functions to be overloaded.
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]
this is | |
---|---|
^$ | first argument |
^^ | null |
^@ | function's this |
const log = console.log^$(console, 'hello:')
log('foo')
// hello: foo
func log(...args) {
console.log(...args)
}
const logHello = log^^('hello:')
logHello('foo')
// hello: foo
const log = console.log^@('hello:')
log('foo')
// hello: foo
this is | |
---|---|
*$ | first argument |
** | null |
func log(...args) {
this.log(...args)
}
log*$(console, 'hello')
func log(...args) {
console.log(...args)
}
log**('hello')