fn
declare a function
<fn> = fn <name>+ <opt>* <arg>* { <statements> }
<arg> = <decl>
| <decl>'?'
| <decl>'...'
<opt> = <opt names> <decl>
<opt names> = <opt name> ['|' <opt names>]
<opt name> = '--' <name>+
| '-' <letterOrDigit>
<name> = <letterOrDigit> <name rest>*
<name rest> = <letterOrDigit> | '-'
Functions in syshell behave like programs: they accept parameters and they have input, output and error streams. Functions preserve data types (instead of converting everything to strings as it is done for external programs). Functions also can change global and captured variables.
Functions can be declared in the scope of the current file or inside another function. Unlike other scripting languages, function calls can be done above function declarations. Functions can not be re-declared.
fn main {
print "Hello, World!"
}
Arguments
Functions can have positional arguments. When function is called, all
positional arguments must be specified, unless the argument is marked as
optional using ?. Optional positional arguments must come
after non-optional. The last positional argument can be specified as
variadic using ....
Arguments are passed following syshell's value semantics, which means that parameters can be changed inside function, but outside of the function there will be no visible changes.
| add two numbers together | |
| optional and variadic arguments | |
| optional and variadic arguments are assigned in the left-to-right order | |
| modifying parameters has no effect on original arguments | |
Subcommands
There is a builtin way to create subcommands in style of
git or kubectl:
# stage files for commit
fn git add $files... {}
# create a commit
fn git commit {}
# update remote repo
fn git push $repo? $refs... {}
# show help
fn git {}
Functions with subcommands should be defined in a single scope.
Formatters
Formatters help to validate or convert parameters before assigning
value to a variable. For example, (int)$n enforces that
positional argument $n is an int. This syntax is covered in
more details in pattern
matching.
enforce all parameters to be integer. $step is an
optional and can be null. |
|
Options
There is a builtin way to handle options. Options must be specified
before positional arguments using --option $var syntax,
where $var is a declaration of a variable, possibly with a
specified formatter.
Options are always optional, option variable is set to null, if option is not specified during the call.
multiple option aliases can be specified using | |
|
use local timestamp formatter to reliably parse
dates |
|
bool options are handled like flags: they don't expect
immidiate argument during the call |
|
Input Stream
Every function might have an input stream, if it was started inside a
pipeline or has a redirect. However, when a sub-function or an external
program are executed, they don't have an input stream enabled by
default, because the input stream must be enabled explicitly with
>>:
# main had stdin (fd 0) as an input stream
fn main {
# input stream is not enabled, cat will have /dev/null as fd 0
cat
# input stream is enabled, cat will inherit stdin
>> cat
}
Read streams to learn more about it.
| square a numbers twice | |
| execute programs that require user input | |