3 things you probably can’t do in yer daddy’s language…

June 12th, 2009

.. but you can in REBOL :) .

Language construct – List / Match

PHP has some “function” called list(). But it looks more like magic (read: very useful but inconsistent internal construct/hack) than a normal element of the language. It is used to deconstruct array and bind it to variables:

list($name, $surname) = Array("Janko", "Metelko");

(I think) you can’t put something function-looking on the left side of equation in any other case and you can’t create “function” that would function something like this in PHP. The docs say this:

Like array(), this is not really a function, but a language construct.

Unlike Factor a function can’t return multiple values in REBOL (and how would you assign them). But of course they can return a block of them. But in this case it’s clumsy and ugly to deconstruct them:

before

response: get-some-response
status: first response
reply: second response
now-use-that status reply

so let’s make our version of list() and call it match:

match: func [ data rule ] [
   parse rule [ SOME [ set W word! ( set :W first data  data: next data ) ] ]
]

And now we can do:

after

match [ status reply ] get-some-response
now-use-that status reply

So we can do ourselves what others would need a language construct for.

Custom “control structure”: exit-if

I was making a command-line application. I had a tons of cases – some at the beginning of code, but also later inside code structure – where I had to exit the app with a message what user of app screwed up. Like “parameters missing…”, “the input file doesn’t exist”, “the data structure is empty”, “Internet is unaccessible”…

So what was common to these things.. the code for all looked something like:

before

if error? try [ *input*: read to-file input-f ] [
    print rejoin [ "input-file " input-f "doesn't exist" ]
    halt
]

if empty? *websites* [
    print "no websites in input file."
    halt
]

Do you see the common repetition? We have functions to remove repetition but how do you factor-out the control structure? Well this should really be no problem with rebol:

exit-if: func [ cond msg ] [ if cond [ exit-with-msg msg  ] ]
exit-with-msg: func [ msg ] [ print rejoin msg halt ]

Two lines of code and we have our custom “control structure” and now we can do on all the places:

after

exit-if error? try [ *input*: read to-file input-f ] [ "input-file " input-f "doesn't exist" ]  

exit-if empty? *websites* [ "no websites in input file." ]

I put control structure in quotes up there because in REBOL the normal if is just a ordinary function too.. as is foreach, either, while.

Custom “function creating function* – WTF??

In JavaScript you create a function like this:

function addTwo(a, b) { return a + b; }

The function keyword is something special. You don’t even think you could create your own version of it… what?? In rebol you create function like this (with a little less noise btw):

add-two: func [ a b ] [ a + b ]

Let’s compare it to few other lines of code:

A: 202
B: mold [ name "janko" ]
C: parse [ a b ] [ a [ b | c ] ]

add-two: is ordinary assigning then there is a word that takes two blocks. We know many such words in rebol, we call them functions. I am trying to say.. a word func that creates functions is (like if and foreach) only a function. And we can create functions of course.

I needed to make a report generator. It was made so that you created a block of callbacks and you just passed the block to the generating function and it did its work. After writing the callback functions I ended up with around 30 functions that all looked pretty much the same. They took a number of arguments and they rejoined the custom strings with those arguments:

before

web: func [ d ][ rejoin [ "^/^/WEBSITE: " d "^/^/" ] ]
keyw: func [ k ][ rejoin [ "  " k " ->^/" ] ]
res: func [ p l t d ][ rejoin [ "    " p ") " strip-html t " : " l "^/       " strip-html d "^/" ] ]

So we create our custom function creating function:

fujoin: func [ args code ] [ func args compose/only [ rejoin (code) ] ]

Now our callbacks look:

after

web: fujoin [ d ][ "^/^/WEBSITE: " d "^/^/" ]
keyw: fujoin [ k ][ "  " k " ->^/" ]
res: fujoin [ p l t d ][ "    " p ") " strip-html t " : " l "^/       " strip-html d "^/" ]

So what…

“So what.. stupid tricks to make code a little shorter” you say? Ok, whatever.. programming to me is about power of expression. I enjoy programming where I can express the logic as cleanly as possible.. where code is only relevant information, the recipe, no noise or boilerplate code, and with REBOL I can do that much better than with languages I used before.

These 3 are all the examples that happened when I was coding this commandline client last week.

So.. can you do this in your daddy’s language?

Read and let read :)
  • del.icio.us
  • Reddit
  • Digg
  • DZone
  • email
  • Facebook
  • HackerNews
  • Twitter
  • StumbleUpon

One Response to “3 things you probably can’t do in yer daddy’s language…”

  1. Steeve Says:

    Some Rebolers should check your site more often because sometimes you reinvent the wheel ;-)

    We don’t need a match function, because SET do the job…

    >> set [status reply ] get-some-response

    >> ? set
    USAGE:
    SET word value /any /pad

    DESCRIPTION:
    Sets a word, block of words, or object to specified value(s).
    SET is a native value.

Leave a Reply