REBOL for COBOL programmers

Go to table of contents Go to feedback page

Code is data

Date written: September 25, 2012
Date revised:
Date reviewed:

This page tries to explain a peculiarity of REBOL that is the result of it being an interpreted language and of using the same notation (the square brackets) for code and data.


A helpful comparison

It might be helpful, if you have had the experience, to recall how, in unix, a file is just a string of bytes, and everything is a file. By using that model of everything being a file, programming can be simplified to operting on strings of characters. A file is a file, a device is a file, the console is a file.

The REBOL series

In REBOL, the thing that many other things are but instances of, is a series. You should go to the REBOL documentation and read the chapter about the "series" datatype. A file is a series of lines, a string is a series of characters, and, important to this discussion, a block is a series of whatever is in the block. The block is an important element of REBOL.

The REBOL block

Blocks are what REBOL uses to hold data. The are indicated in the source code by the square brackets. There are functions that operate on blocks, pick, first, second, third, foreach, head, tail, and so on. When you read a file with the "lines" refinement, what you get is a block of strings. When you request a file name with the "request-file" function, you get a block of file names.

But wait, there's more. If you look at REBOL code, you see that in the coding for a function, the code is in a block. For an "if" function, the code to execute when the condition is true is in a block. You can "do" a block if the block has code in it. Blocks are everywhere, and they can hold code and data.

Because blocks can hold code and data, you can do interesting things that would never enter your mind as possible, being a COBOL programmer. For example, if you had, in WORKING-STORAGE

01  ADD-SALES-TAX.
    03  FILLER PIC X(15) VALUE "IF TAXABLE = 1 ".
    03  FILLER PIC X(35) VALUE "COMPUTE SALES-TAX = AMOUNT * 0.065 ".
    03  FILLER PIC X(35) VALUE "COMPUTE TOTAL = AMOUNT + SALES-TAX ".
    03  FILLER PIC X(05) VALUE "ELSE ".
    03  FILLER PIC X(20) VALUE "MOVE AMOUNT TO TOTAL".
you could not, in COBOL, later say
PERFORM ADD-SALES-TAX.
because you can't execute your data, you can't PERFORM a WORKING-STORAGE item. But it would be handy. What if you were writing a general-purpose program and you wanted a way to configure different methods of sales tax computation. Normally, you would have to make some switches and tables and so on and try to define them in such a way that you could define different tax computation schemes. And then, if you overlooked something, you might find some calculation scheme that your configuration method could not handle. But what if you could store, in each customer data record, a potentially unique calculation defined in COBOL source code and then execute that source code? There would be no calculation scheme you couldn't handle, because you could, if you had to, code a different calculation for each customer.

In REBOL, there is the potential for such a plan of action. You could code

ADD-SALES-TAX: [
    either TAXABLE [
        SALES-TAX: AMOUNT * 0.065
        TOTAL: AMOUNT + SALES-TAX
    ] [
        TOTAL: AMOUNT
    ]
]
You could put the above block into a data record, and then at some point
do ADD-SALES-TAX
to calculate the tax. If necessary, every customer could have a unique calculation.

You can extend the above idea in whatever way you can dream up. You can store code as data. You can execute data if it happens to be code. The possibilities are interesting.