Subroutines are a set of rules — a Rule. Subroutines are defined only (there is no need to declare them). Subroutine names are one or more lowercase letters within square brackets.
Say you did not like the
^ operator, and you like Perl. You can do this.
Which shows that
say is now a print function and that subroutine arguments pass as the parameter array, and that
^ echos all its arguments similar to Perl. (See #Subroutine Parameters next.)
$0 (which is not like Perl's) is used as a return value for almost all operators and builtins; and
$_ (which is like Perl's) for many default arguments — but not all.
A subroutine is called just like any builtin, followed by any arguments which are stored in the special parameter variable
@_ as a list. Parameters are passed by copy.
product 2 4 6 8 ; call subroutine with four numbers ^ ; print result (in $0) [product] ; subroutine name = 1 ; set $0 to 1 @for @_ ; each argument value in $_ *= $_ ; result stays in $0 @end
A subroutine ends at the end of the file or with any following subroutine definition. The loop termination operator,
@end, is not needed if it would be the last operator of a subroutine.[Which is how all block end operaters work.]
The parameter variables are unique and no others starts with
@— it's syntax was stolen from Perl just for the parameter arguments.
Currently there is no return value of subroutines, though any variable will do. The "return value" is generally by
$0, as in the example, but since all variables are global (except as defined below) any variable can be used.
product 2 4 6 8 ^ $p [product] = p 1 @for @_ *= p $_ ; result in $p
Like Perl, arguments are passed as an array, with multiple arguments concatenated.
product (2,4,6,8) product (2,4) 6 8 = b (6,8) product (2,4) $b
The Rulz convention for subroutine names is "the shorter the better"; which, for short Rulz programs, "p" would be used rather than "product".
Redefining a subroutine is not an error; it wil simply overwrite the existing one.
@_ list of parameters @# count of parameters @* all parameters expanded to a string @0 first parameter @1 second parameter, etc., with @9 the limit @A first parameter @B second parameter, etc., with @Z the limit
The special variable
$@ is an alias to
@*.[Which is only useful for in an interpolated string and might go away.]
Subroutines with or without any parameters, whether expecting them or not. All of the following would print nothing (but a newline) if called with no arguments.
[sub] ^@_ [sub] ^@* [sub] ^@0 @1 @2
The print operator sees NULL and empty lists as empty strings.
For Rulz any variables not defined are read as NULL. (And NULL is always converted to the "zero" or "empty" value for other type; which are false, 0, 0.0, "" and () for boolean, integer, float, string and list respectively.)
Subroutine attributes are for saving special variables, "private" variables (same as Perl's "my"), "local" variables (same as "static" in PHP) and named arguments.
Attributes have the format id:var[=value][,var[=value]...] and follow the subroutine name separated by spaces.
$_ special variable is automatically saved and restored. Other special variables are saved by the s: attribute. This attribute does not separate it's arguments with commas (so to allow the saving of
$,). (See RulzSplat.)
sub foo bar [sub s:.] = . "\r\n" ^ @0
That subroutine changes the line termination special variable,
Private variables, Perl's "my", is implemented as p:.
[sub p:p] = p 1 @for @_ *= p $_ @end = $p
There can be multiple variables per attribute and optionally can be set to a default value. (The default is NULL.)
A Local variable, like a PHP static varibale, which retains it's value between subroutine calls, is defined by l:.[That is the letter "el", not the number "1". It is, frankly, really bad of font designers to allow two different charcaters to be nearly indistinguishable — in some fonts they differ by a single pixel.]
@for (1..4) sub [sub l:s] += s ^ $s
$ ./rulz local.rul 1 2 3 4
Subroutines can recurse.
rsub [rsub l:s=1] += s >? $s 4 .. ^ $s rsub
Named subroutine arguments are designated by a:.
sub foo [sub a:s] ^"<sub>$s</sub>"
Assigning a value make the argument default (if not provided to the subroutine) no longer NULL but the attribute value.
exit ; "normal" exit exit 2 ; "error" exit [exit a:e=0] .^ $e
The arguments are positional, not sorted.
It is possible to enter a subroutine at any point. However, an entry point into the body of a loop currently results in undefined behavior.
Subroutine entry occurs by the jump operator along with a subroutine name index, just like a string or array index — but only syntactically.
A subroutine call, a subroutine name as an operator (first in a rule), is basically shorthand for a jump to a subroutine's 0th entry point.
Jumping past the end of a subroutine is a no-op.
There are three file "forms" for a Rulz file. The first is with one or more rules.
# form one ^ just some rules
The second contains rules followed by one or more subroutines.
# form two sub [sub] ^ in subroutine
In this form all rules before any subroutine(s) are call "Top Rules".
The final form contains just subroutines and are useful as loadable libraries. Given this file:
# lib.rul - an API [sub] ^ sub
.< lib.rul sub
Like Perl there are some special subroutines that are run internally.
-run first after a program has been loaded.
-run last before program termination.
-optionally run before each and every other subroutine is run.
_sub subroutine to run the
$SUB Rulz variable needs to be set to true (default is false), which is:
= SUB 1
Unlike Perl there can be only one of those subroutines per program.
-all further lines are ignored.
_stop is not really a subroutine, of course; it just has the same format.
[_stop] that line and all others disappear into...
(It just tells the load function to immediately stop.)
The begin routine disappears after being run.
These special subroutines, which are processed after a progam is loaded but before any Top Rules are run, are for creating data — not really subroutines, they just share the syntax.
_dataall lines following (until EOF or another subroutine) placed into
_data special subroutine is like Perl's
__END__ token. It is not like Perl's DATA file handle however; all text following it populates the Rulz variable $DATA as a string. Any whitespace is retained.
-all lines following placed into a list.
^ $var ; prints (1,2,"a") [_list var] 1 2 a
-all lines following to define constants.
^ FOO BAR ; prints 1 2 [_const] FOO 1 BAR 2
-all lines following define constants starting from 1.
^ FOO BAR ; prints 1 2 [_enum] FOO BAR
Any leading and trailing whitespace, blank lines and comments are ignored.
None of those are retained after the data are created.