Question

I have attempted to pass a function as a parameter in the REBOL programming language, but I haven't figured out the correct syntax yet:

doSomething: func [a b] [
    a b
    a b
]

doSomething print "hello" {This should pass print as the first argument and "hello" as the second argument.}

This produces an error, since the print function is being called instead of being passed:

hello
*** ERROR
** Script error: doSomething does not allow unset! for its a argument
** Where: try do either either either -apply-
** Near: try load/all join %/users/try-REBOL/data/ system/script/args...

Is it possible to pass the print function as a parameter instead of calling the print function?

Was it helpful?

Solution 2

You have discovered that by the nature of the system, when the interpreter comes across a WORD! symbol type which has been bound to a function, it will invoke the function by default. The default interpreter seeing a GET-WORD! symbol type, on the other hand, suppresses invocation and just returns the value the word is bound to.

The evaluator logic is actually rather straightforward for how it reacts when it sees a certain symbol type. Another way of suppressing invocation is the single quote, which will give you a LIT-WORD! symbol... but these become evaluated as the corresponding WORD! when it sees them:

>> some-word: 'print
>> type? some-word
== word!

In fact, the behavior of a GET-WORD! when the evaluator sees it is equivalent to using the GET function with a WORD!

doSomething: func [a b] [
    a b
    a b
]

doSomething get 'print "hello" {Message}

The interpreter sees the LIT-WORD! 'print and evaluates that into the WORD! for print, which is then passed to GET, which gives you a FUNCTION! back.

Simplicity of the interpreter logic is why you get things like:

>> a: b: c: 10 print [a b c]
10 10 10

Due to the nature of how it handles a SET-WORD! symbol followed by complete expressions. That yields also the following code printing out 20:

if 10 < a: 20 [
   print a
]

Other languages achieve such features with specialized constructs (like multiple initialization, etc.) But Rebol's logic is simpler.

Just wanted to elaborate a bit to help explain what you were looking at. My answer to this other question might provide some more insight into the edge cases, historical and future: "When I use error? and try, err need a value"

OTHER TIPS

I've found the solution: I only need to add : before the name of the function that is being passed as a parameter.

Here, the :print function is being passed as a parameter instead of being invoked with "hello" as its argument:

doSomething: func [a b] [
    a b
    a b
]

doSomething :print "hello" {This should pass print as the first argument and "hello" as the second argument.}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top