|REBOL 3 Docs||Guide||Concepts||Functions||Datatypes||Errors|
|TOC < Back Next >||Updated: 28-Aug-2010 Edit History|
The purpose of this section is to give you a quick summary of how new functions are created. If you want to read more about functions in general, see Functions.
There are many types of functions and a variety of ways to define them.
The most common way to define a function is with func.
Here is a simple example:
sum2: func [a b] [a + b]
Now you can call the new function with a line like:
print sum2 10 20 30
As shown above, func takes two blocks as arguments:
func [specification] [body]
|specification||defines the function's interface, including arguments, local variables, and documentation.|
|body||provides the code that is evaluated when the function is called.|
After the new function is created, it is returned from func. In the example the sum2 variable is set to it.
Above, func is actually a function itself that is used to create a new function. This happens at run-time, so new functions can be defined at any time.
There are also other functions for creating functions:
|funct||assumes variables are local by default|
|does||shortcut when no specification is needed|
|has||shortcut when only local variables are used|
|make||the low-level function constructor|
See Functions section for more on those.
The sum2 example above did not require arguments of any specific type. That means you can provide any type of data as arguments:
print sum2 10:00 2:30 12:30
print sum2 1-Jan-2009 10 11-Jan-2009
However, if you need to restrict argument types, you can do that within the specification block.
Here we restrict a and b to be integer! only:
sum2: func [a [integer!] b [integer!]] [a + b]
Multiple types are also allowed. Here we've added decimal! as well:
sum2: func [ a [integer! decimal!] b [integer! decimal!] ][ a + b ]
Now, if you provide two times as arguments, you'll get an error:
print sum2 10:10 2:30 ** Script error: sum2 does not allow time! for its a argument
In addition to datatype names, you can also use typeset!, which are groups of datatypes. (To see a list of predefined typesets, type ? typeset! at the console.)
sum2: func [ a [number!] b [number!] ][ a + b ]
While you're in the process of creating the function, it is useful to add a few comments to the definition.
sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" ][ a + b ]
You can now ask for help about the sum2 function:
? sum2 USAGE: SUM2 a b DESCRIPTION: Adds two numbers and returns the result. SUM2 is a function value. ARGUMENTS: a -- The first number (number!) b -- The second number (number!)
A little documentation can go a long way.
Sometimes you find you need some optional variations in the behavior of your functions. In REBOL we add a refinement! for each such option.
A simple example helps show it. Take the above code again, but this time add a refinement that indicates you want only a truncated integer result:
sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" /int "Return integer only (truncated)" ][ either int [to integer! a + b] [a + b] ]
We've added /int as a refinement and provided a help string for it.
Now you can write:
sum2 1.2 3.9 5.1
sum2/int 1.2 3.9 5
Refinements are also used to provide optional arguments.
Let's say you want to provide an optional argument for rounding the result. You can do this by adding a refinement followed by its optional argument:
sum2: func [ "Adds two numbers and returns the result." a [number!] "The first number" b [number!] "The second number" /rounded "Return a rounded result" precision [decimal!] "The rounding precision" ][ a: a + b if rounded [a: round/to a precision] a ]
Trying it out:
sum2 1.23 3.94 5.17
sum2/rounded 1.23 3.94 .1 5.2
Notice that the optional argument is added to the end of the argument line.
When the refinement is used, the optional arguments have to be provided. When the refinement isn't used, the optional arguments are set to #[none].
Sometimes it is useful to define additional variables local to the function. By convention, the /local refinement is reserved for this purpose.
|TOC < Back Next >||REBOL.com - WIP Wiki||Feedback Admin|