REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 22-Nov-2013 Edit History  

REBOL 3 Guide: Code: Defining functions

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.


Defining 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

General form

As shown above, func takes two blocks as arguments:

func [specification] [body]


specificationdefines the function's interface, including arguments, local variables, and documentation.
bodyprovides 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.

Other methods

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:

functassumes variables are local by default
doesshortcut when no specification is needed
hasshortcut when only local variables are used
makethe low-level function constructor

See Functions section for more on those.

Restricting arguments

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
print sum2 1-Jan-2009 10

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.)

For example, number! is defined as a typeset that includes integer!, decimal!, and percent!.

sum2: func [
    a [number!]
    b [number!]
] [
    a + b

Embedded documentation

While you're in the process of creating the function, it is useful to add a few documentation strings to the definition.

For example:

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
    SUM2 a b

    Adds two numbers and returns the result.
    SUM2 is a function value.

    a -- The first number (number!)
    b -- The second number (number!)

A little documentation can go a long way.

Function refinements

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
sum2/int 1.2 3.9

Optional arguments

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]

Trying it out:

sum2 1.23 3.94
sum2/rounded 1.23 3.94 .1

Notice that the optional argument is added to the end of the argument line.

Values of optional arguments

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].

/local refinement

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 > - WIP Wiki Feedback Admin