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-



-- 
To unsubscribe from this list, just send an email to
[EMAIL PROTECTED] with unsubscribe as the subject.

Reply via email to