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

[enum] Re: Some other questions

 [1/2] from: joel::neely::fedex::com at: 22-Nov-2003 8:48


Hi, again, Mike, Mike Loolard wrote:
> 2) How do you create custom types ? > I am talking of a way to emulate the typedef behavour in C ? > How would you go to create an "enum" type in REBOL ? >
Strictly speaking, there are two answers to your first question: 1) You can't. But REBOL has a very rich set of types already, so you can often find a type that suits your purpose (if you ask yourself the right questions!) 2) You can create objects, and use those as prototypes to creat other objects. There's a real problem is with your second question (and if you don't read anything else I write, PLEASE remember this one!) COBOL is alphabet blocks. C is a set of tinkertoys. Java is an Erector Set (IIRC similar to Meccano in Europe?) with all kinds of braces, motors, girders, nuts, and bolts. Perl is a Swiss-army chainsaw. REBOL is modeling clay. Learn to use each one according to its own nature. Let's talk about question 3 and then return to the first one. As I said above, we must first ask ourselves the right questionS. If your question is really How can I create a set of names for distinct, related values to use in my REBOL program? Then the answer is easy: words! Suppose I am doing something with personnel data, and want to represent the status of each employee. I could do something like the following: employee: make object! [ ID: 0 name: "" hire: now/date status: 'full-time ] Notice that the STATUS attribute is a word! value, whose name is chosen for mnemonic value. That's all there is to it. Now let's proceed to "hire" some people, with: bob: make employee [ ID: 1234 name: "Robert R. Robertson" hire: 01-Jan-1997 ] carol: make employee [ ID: 2345 name: "Carolyn C. Carroll" hire: 14-Feb-1998 ] ted: make employee [ ID: 3456 name: "Theodore T. Theoden" hire: 27-Nov-1999 status: 'part-time ] alice: make employee [ ID: 4567 name: "Alicia A. Allison" hire: 31-Dec-2000 status: 'leave ] Notice that BOB and CAROL are created with the default status of full time, while TED and ALICE each have different status. Here we had to "quote" the words, making them LIT-WORD! values, to keep REBOL from trying to evaluate them. We don't care about whether there's a value associate with e.g. LEAVE , but simply want to use the word itself as a label. Let's use a block as our pretend database: all-employees: reduce [bob carol ted alice] The reason we had to REDUCE that block is that here we don't want a block of words, but want a block containing the objects that those words are set to. (We could also have written a "constructor" function which would make a new employee from the arguments passed to it, and would append that new employee to ALL-EMPLOYEES at the same time.) Then we can produce an employee report, grouped by status with the following (rather inefficient!) function: group-report: func [ /local count ][ foreach [ status title ][ full-time "Full Time (at least 35 hrs/wk)" part-time "Part Time (up to 34 hrs/wk)" leave "Leave of Absence (half benefits)" suspended "Disciplinary Suspension (no benefits)" terminated "Not Here (no further information available)" ][ count: 0 print [title newline] foreach emp all-employees [ if emp/status = status [ print [tab emp/hire tab emp/ID tab emp/name] count: count + 1 ] ] print [newline count "employees in this status" newline] ] ] When we evaluate that function, we get:
>> group-report
Full Time (at least 35 hrs/wk) 1-Jan-1997 1234 Robert R. Robertson 14-Feb-1998 2345 Carolyn C. Carroll 2 employees in this status Part Time (up to 34 hrs/wk) 27-Nov-1999 3456 Theodore T. Theoden 1 employees in this status Leave of Absence (half benefits) 31-Dec-2000 4567 Alicia A. Allison 1 employees in this status Disciplinary Suspension (no benefits) 0 employees in this status Not Here (no further information available) 0 employees in this status Notice that the second argument to the outer FOREACH in the function above is a block containing alternating WORD! and STRING! values: the word is the name/symbol of a status, and the string is the associated description. (In a real application, this would be global to the entire application, of course!) Since we didn't REDUCE that block, we literally have words and strings. The REBOL word type can be used in this way -- as a symbol with no associated value -- in the same way that one might use atoms in LISP, scalar types in Pascal, or (sort of) enum symbols in C. But remember that C enum types actually have associated values, which is *not* the case with REBOL words used as above. However, (and finally, for this sub-question), we could have begun by defining our status titles *as* the values of a set of words, and then just used the names of the strings: full-time: "Full Time (at least 35 hrs/wk)" part-time: "Part Time (up to 34 hrs/wk)" leave: "Leave of Absence (half benefits)" suspended: "Disciplinary Suspension (no benefits)" terminated: "Not Here (no further information available)" when we subsequently created our employees: employee: make object! [ ID: 0 name: "" hire: now/date status: full-time ] ; and so on, through... alice: make employee [ ID: 4567 name: "Alicia A. Allison" hire: 31-Dec-2000 status: leave ] All employees created with a status of FULL-TIME will have the title string in their object, but it is *a*reference*to*the*same* string, not a copy of the string, so there's no wastage of memory. There are certainly some pros-and-cons here, but I wanted to point out the reference-vs-copy issue, as it can lead to significant differences in how you can use strings in REBOL vs some other languages. FINALLY (whew!) to return to your first question: You can't create your own types, so even if you use objects or words to implement your application's concepts, there's no way (aside from writing your own run-time checks) to enforce the rules about those conventions. A function to perform some operation on an employee would still have to be written something like flibbertigibbet: func [emp [object!]] [...] which would pass the automatic argument type tests if *ANY* object were passed, not just one of your employee objects. Likewise, you can write a function which requires a word as one of its arguments, but there's no way to require that it be one of a particular set of words (e.g. the status of an employee) without including in the function your own checking status-words: [full-time part-time leave suspended terminated] ;... somefunction: func [blahblah [word!] ...] [ either find status-words blahblah [ ;... proceed normally ][ ;... generate your own error explicitly ] ] Hope this helps! -jn-

 [2/2] from: moliad:aei:ca at: 22-Nov-2003 11:33


Mike Loolard wrote:
> 2) How do you create custom types ? > I am talking of a way to emulate the typedef behavour in C ? > How would you go to create an "enum" type in REBOL ? >
joel gave you a very in-depth answer, I'll proceed with a different perspective. in most languages, you have a very strict syntax which identifies types, statements, functions, reserverd words, etc, etc. in rebol you can throw all that thinking away. Like joey said, there is NO syntax in rebol. this being said, creating your own statement which initializes a series of words (in c you'd call these variable names) is quite easy. although, they won't be datatype per say, because rebol lets you manage code as if it where content, you can easily create your own "statements" here is a quick func which will simulate your enum statement in C. enum: function [word-block][counter][ counter: 0 foreach word word-block [ set in system/words word counter counter: counter + 1 ] ] ; you can then use your enum "statement" like so: enum [null eine zwei drei vier funf] print eine ==1 print vier ==4 if you want you can also call protect on the new words, if you want to be sure their value never gets overiden in your global namespace, but usualy, that is not a good idea unless you really need to. joey's analogy of rebol being clay really makes sense. you can "Shape" rebol to be what you need it to be. in most other language, you have to use the contstructs they give you, however cool they are, you still are tightly bound to them. HTH! -MAx