An Enumerated Type For REBOL 2

I’ve uploaded a script (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. :)

Backstory

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

Tags:

2 Responses to “An Enumerated Type For REBOL 2”

  1. Gerard Cote Says:

    Hi Fork,

    Glad I found your recent post about your implementation of enum.r.

    In fact as I recently began to learn more deeply about existing programming languages concepts, since I want to be able in the long run to write my own programming language to help newcomers to program in a high level pseudo-code language and I would like to use REBOL as my first experimental tool to support my learning in this domain - because it seems to have some advantages to me - but also some caveats.

    During the last week-end I found that the Caml Programming language supports the feature of being able to define new user-defined data types, and especially there is an example about how to simply define an enumerated type like the one you just implemented in REBOL- since this feature is not natively supported by the language.

    So I would like to thank you for your effort and let you know that it will be at least useful to me before someone else finds it in the library.

    To promote its use by others, I suggest you leave some entry in the Mailing list too.

    When I’l be ready to experiment with your enum.r I’ll let you know too about my feelings - but sure it will help to implement some of my work from now.

    It’s fun you have such a clear image about what is needed to implement rightly the tools required for keeping to a minimum the efforts to debug implemented software. This is also one of my main concerns since it is rarely if not never implemented right on all the line…

    If and when I will define other useful utilities I’ll let you know too.

    Thanks again
    Gerard

  2. Hostile Fork Says:

    Hello Gerard, you’re welcome—and thanks for taking a look at this!

    Certainly it is good to study a wide variety of programming languages before designing an all new one! :) A lot of people have thought about the best way to start, and this has resulted in things like LOGO and Karel the Robot. REBOL seems like a very good replacement for LISP in teaching.

    But most every course introduce students to programming via some variant of “I’m controlling a robot out in empty space”. Though it can feel empowering, I don’t think it’s a good foundation—it emphasizes the power of single lines of code, instead of imagining how those manipulations are often at odds with a greater architecture.

    So I feel like early programming education should start with something like the game The Incredible Machine. Then perhaps move to solving simple problems with Turing Machines. These are better for teaching foundations of software because they emphasize problem-solving with patterns, rather than by direct control of the CPU.

    Anyway…if you like the enum.r then please feel free to post it on the REBOL list (if you have something to say about it)! I myself am busy trying to push other agenda items and meddling in other ways… :)

Leave a Reply


Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported