Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] REBOL Zen / idioms

From: jeff::rebol::net at: 3-Mar-2001 3:09

There's a certain zen to REBOL and it takes time to understand-- something that I am always learning. REBOL has a lot of what might seem like idioms, which really are ways to do things that make life a lot easier. They stem from the craftsmanship in REBOL, the rather lengthy effort that went into its design, implementation and polish. Many problems you face in programming have a nicely crafted solution sitting inside this little binary interpreter, just waiting for you to discover it when you need it. The code that comes from REBOL should demonstrate that Zen because we all are lucky in that we can pick Carl's brains over the challenges we encounter. Also, we're lucky because we get to write REBOL code as an occupation, so we get to find all those little crafted edges inside. I've always hoped to pass on what little I have learned of the Zen of REBOL to any who would walk in that path. Here is an example of some REBOL Zen style idioms. ============================================ Consider a block of similar objects: block: [make object! [name: "foo" phone: #222-1111 ... ] ... ] Now you're writing a function and you have this block and it is really long with many of the same kinds of objects, but you need to see if there is an object which has the name field set to "Waldo" and you need to see if the waldo object's phone field is set to none, If you don't find this object you want to do somehing. If you do find waldo and waldo has a phone you want to call waldo, otherwise you want to complain that he doesn't have a phone. Some people might code it like this: find-waldo: func [block [block!] /local found waldo no-fone?][ found: false foreach obj block [ if obj/name = "waldo" [ waldo: obj found: true no-fone?: not none? obj/phone ] ] if not found [wheres-waldo?] either no-fone? [waldo-has-no-phone][call-waldo waldo/phone] ] That's a fair approach, similar to how you might tackle the problem in basic, maybe. But with REBOL you can get much more done in place. Most things return meaningful values so the left side of most functions represent an excellent place to dock another useful function, save space, save steps, and preserve the utility of results. How about this: find-waldo: func [block [block!] /local result][ if not result: foreach obj block [ if obj/name = "waldo" [break/return any [obj/phone yes]] ][wheres-waldo?] either issue? result [call-waldo result][waldo-has-no-phone] ] Okay, so we have less local variables, the code is smaller and therefore is more efficient usually (and in this case definitely). The first example trudged through the whole block before deciding the outcome, where above we BREAK/return as soon as we find waldo. The FOREACH will return the last evaluation, so if FOREACH makes it through the whole block with out ever finding waldo it will return a NONE from the last evalutation of the IF statement. We use the result of FOREACH to immediately determine if we found waldo. Now if result is not a NONE, it will be either an issue!, waldo's phone number (#222-111-3333), or a TRUE value (yes). The TRUE is arbitrary since we just have to return a non false / non none from BREAK/return and we only check if we have an issue which means it must be Waldo's phone number. Programmers will have different styles, but the language also has a style of its own. With REBOL it usually comes down to taking a function, writing it, then rewriting it a few more times, carving out the fat while expanding the capability. As a general rule most REBOL functions that are written can be reworked to accomplish more, to provide more use in the same amount of space or less. Code in the eye of the fly and seek to know the true path of the REBOL way! :-) -jeff