Function gets data, does work and optionally returns value. Each function is composed of signature and statements block. In the signature there is the function key (name) and list of expected parameters. After the signature comes the statements block which can be composed of one or more statements.
In Till there is always a returned value, and the returned value of a function is the returned value of its last executed statement. If the statements block does not contain programmatic entities that change the flow of a program and end the function before its last statement, then the returned value will be the (returned) value of the last statement of the statements block. Otherwise, whenever a flow is terminating the function, the last statement of the flow will yield the returned value of the function.
In case where the function executes only one (one-line) statement, it is possible to append that statement to the function signature in the same line of code (“one-line-function”).
Here are some excerpts from Pi Calculator Project, followed by analysis.
setstate anyway:
!if anyway parameter is omitted, enforce setting
null anyway ? anyway T
storage.set 'power' power anyway
storage.set 'denominator' denominator anyway
storage.set 'sum' sum anyway
storage.set 'iternums' iternums anyway
storage.set 'calcpis' calcpis anyway
storage.set 'deltas' deltas anyway
storage.set 'durs' durs anyway
! remove all application state from storage
dropstate: statekeys k ~ storage.unset k
- declare function “setstate” with parameter “anyway”
- if “anyway” is NULL, set “anyway” to TRUE
- in the following statements, run system function “storage.set” with parameters: key, value (variable) and anyway (value of parameter “anyway”)
- declare one-line-function “dropstate” that have one statement
In Till function, scalar parameters are passed by value, and parameters of other types are passed by reference.
not hasin ?
pause 0.7
print 'Set RESTART flag to FALSE, and run again!'
%% F
^
^
setstate RESTART
VALIDATESTORAGE ? %% validatestate \ getstate
nostate not storage.exists checkkey
REPORT ? nostate ? print 'state not exists' \ showstate
Functions in this example are: “setstate”, “validatestate”, “getstate” and “showstate”. Function “setstate” is called with parameter “anyway” that gets the value of variable “RESTART”.
System functions in the example are: “not”, “pause”, “print” and “storage.exists”.
Any number of last parameters can be omitted from the calling statement, and the function will refer to these parameters as NULL:
go:
not init ? %
~
calculate
setstate
^
Function “setstate” is called without parameters, thus “anyway” will be NULL.
Passing and using lists in functions
nums orignums 1 2
pkv 'orignums' orignums
pkv 'nums' nums
func1 nums
pkv 'nums' nums
pkv 'func2(nums)' func2 nums
print 'nums gets orignums'
nums orignums
pkv 'func3(nums)' func3 nums
func1 data:
pkv 'data' data
data <- 3
pkv 'data' data
func2 pnums:
result ''
max len pnums
pnums n ~
result ++ n
max --
max ? result ++ ' > '
^
result
func3 pnums:
_localnums pnums
_localnums 0 100
_localnums
pkv k v: print k + ': ' + v
orignums: [ 1, 2 ]
nums: [ 1, 2 ]
data: [ 1, 2 ]
data: [ 1, 2, 3 ]
nums: [ 1, 2, 3 ]
func2(nums): 1 > 2 > 3
nums gets orignums
func3(nums): [ 100, 2 ]
- function “func1” has parameter “data” that gets reference to “nums”
- function “func2” with parameter “pnums”, returns string scalar “result”
- function “func3” gets list variable, copies it to local list “_localnums” that is returned to the caller after changes
- function “pkv” gets two parameters “k” and “v”, and returns the result of system function “print”
Well-Defined List Parameter
In Till, variable names that have at least two characters and end with “s”, are well-defined list variables, and if a function parameter meets this criterion, it will be a well-defined list parameter, and will be fit for all list related activities: list position, set, iterator and assignment.
nums 1 2
data [ ]
print 'show nums'
show nums
print 'show data'
show data
! uncomment to raise an error
!show 1
! function 'show' with (well-defined) list parameter 'items'
show items:
itemsnum len items
print 'items number: ' + itemsnum
not itemsnum ?
print 'No items to show'
\
print 'first item: ' + items 0
print
print 'all items:'
items item ~ print item
^
print
Passing and using records in functions
In the reference there are numerous programs that demonstrate how to use records as function parameters. Here is program “record-func-rec.till”:
country origcountry { name 'Fiji' }
go:
! country record is passed by reference
print 'country record in go function:'
print country
print
print 'call function `func`'
func country
print
print 'country record in go function:'
print country
print
! reset country record
country origcountry
print 'country record in go function (after reset):'
print country
print
print 'call function `func2`'
func2 country
print 'country record in go function:'
print country
func rec:
! country record will be changed in this function
rec 'name' 'Faroe'
func2 rec:
! country record will not be changed in this function
localrec {}
localrec rec
localrec 'name' 'Faroe2'
print
print 'local record in func2:'
print localrec
print
country record in go function:
{
name: 'Fiji'
}
call function 'func'
country record in go function:
{
name: 'Faroe'
}
country record in go function (after reset):
{
name: 'Fiji'
}
call function 'func2'
local record in func2:
{
name: 'Faroe2'
}
country record in go function:
{
name: 'Fiji'
}