Feed Icon RSS 1.0 XML Feed available

An Enumerated Type For Rebol2

Date: 13-Jun-2009/16:16


Characters: (none)

I've uploaded a script called enum.r to rebol.org, which implements enumerated types. Although I typically prefer catching these things at compile-time instead of run-time, I'm pretty pleased with how it works. Especially cool is that I could add a powerful version of this language feature in only about 60 lines of code!!
Note That figure doesn't include the comments and the regression tests. I included those in the script, but they are not necessary to use the enum itself.
I called it "powerful" because it does more than just ensure assignments to objects use legal possibilities. Here's a demo to show it off, and bear in mind that there's no native support for enumerations in Rebol:
>> fruit: make-enum-type [apple orange banana mango]

>> favorite_fruit: make-enum fruit 'apple

>> set-enum favorite_fruit 'shoe
** User Error: illegal enum value ( shoe ) when 
     possibilities are [ apple orange banana mango ]

>> switch-enum favorite_fruit [
     orange [print "orange"]
     mango [print "mango"]

** User Error: missing switch-enum cases for [ apple banana ]

>> switch-enum/default favorite_fruit [
     mango [print "mango"]
     apple [print "apple"]
     banana [print "banana"]
] [print "other stuff"]

** User Error: switch-enum specifies a /default which is 
   more clearly expressed as case ( orange )

>> switch-enum favorite_fruit [
     appel [print "apple"]
     bananna [print "banana"]
     orange [print "orange"]
     mango [print "mango"]

** User Error: illegal case values for switch-enum
     [ appel bananna ] when possibilities are 
     [ apple orange banana mango ]
The syntax isn't necessarily ideal, but that's a lot of features for 60 lines of code!
It makes me reconsider the tradeoffs when compared with gigantic compilers. Although static analysis tools are necessary for huge codebases, the Rebol approach might be able to reduce the amount of code to a manageable size. Perhaps then, one can verify it is correct by actually reading it. :)


My first introduction to Rebol was in 2007. Someone had used it to write an installation script for a software package, and I was trying to run that script. It had gone into a loop--I'd push a "Next" button, yet wind up back at an earlier step. Since I'd been meaning to learn Rebol anyway, I decided to dig in and figure out what the deal was.
After an hour or two of coming up to speed on the codebase and Rebol, I found the culprit. A routine that was reading state out of CGI variables had left a carriage return in the step name. A switch statement thus didn't match step3^/ to the step3 case... so some important code related to moving the process forward was skipped.
This classic bug is the exact reason I tend to be frustrated with today's casual interpreted languages. They lack features like type safety. By contrast, C++ catches similar errors before a single line of code starts running:
enum fruit { apple, orange, banana, mango};
enum step { firstStep, secondStep, thirdStep};

int main() {
    fruit f1 = apple; // legal
    step s1 = secondStep; // legal
    fruit f2 = thirdStep; // compiler catches error, not a fruit!
    fruit f3 = bananana; // compiler catches error, spelled wrong!
    step s2 = "firstStep"; // compiler catches error, strings aren't steps
    step s3 = "firstStep\n"; // compiler will catch this error too
Rather than blame Rebol for the problem, I decided to look into whether the language had a "right answer". It didn't seem to, but people on the AltME bulletin board helped me work through what might be possible. I made a first draft implementation, and started doing some improvements. Was about half of the way done before I got busy with something that was higher priority.
While going through some old files, I found the script and decided to finish it so that someone else might actually find it useful. I completed the half-done speed improvements, added more checks for the /default refinement, and made some meaningful error messages. So here it is... better late than never, right?
It's my belief that if people were to use this enum in their existing Rebol codebases then it would help catch many classes of bug. (Such as the one which initiated this project.)
Business Card from SXSW
Copyright (c) 2007-2015 hostilefork.com

Project names and graphic designs are All Rights Reserved, unless otherwise noted. Software codebases are governed by licenses included in their distributions. Posts on blog.hostilefork.com are licensed under the Creative Commons BY-NC-SA 4.0 license, and may be excerpted or adapted under the terms of that license for noncommercial purposes.