[REBOL] Re: make <object-type> append
From: joel:neely:fedex at: 14-Jun-2001 7:52
Hi, Scott,
Forgive me if I insult your intelligence by proceeding in very
small steps; that's just my own style for picking apart the
pieces of a puzzle with several components, so it's about me
and not about you.
GS Jones wrote:
...
> account: make object! [
> name: make string! 100
> ]
> account: make account [
> balance: $2000
> ]
>
> This sequence creates:
>
> make object! [
> name: ""
> balance: $2000.00
> ]
>
First tricky point: MAKE requires two arguments, a type and
a spec. However the type parameter can be an example or
prototype, instead of being a literal type. If the first
argument to MAKE is an object, MAKE will create another object
with all of the attributes of the prototype. However, the
second argument -- the spec -- is still required, as REBOL
non-syntax doesn't cater well to variable numbers of arguments.
Therefore, if we have
>> source account
account:
make object! [
name: ""
balance: $2000.00
phone: #
state: ""
]
(the final state of your transcript), we can say
>> other-account: make account []
>> source other-account
other-account:
make object! [
name: ""
balance: $2000.00
phone: #
state: ""
]
So (pardon the reiteration) MAKE always takes two arguments:
1) a (proto)type, and
2) a spec (which provides attributes, in the case of an
object creation.
> Now for the make -type- append version:
>
> account: make account append [
> phone: make issue! 10] [state: make string! 2]
>
> Adds two fields to the object:
>
> make object! [
> name: ""
> balance: $2000.00
> phone: #
> state: ""
> ]
>
At this point, it's important to parse that expression to see
what's happening. We could have written that last line as:
>> account: make account (append [phone: make issue! 10]
[state: make string! 2])
(***WITHOUT*** the line break; unlike strings and blocks,
REBOL won't continue parens in interactive mode.)
The point is that the second argument (spec) to MAKE is simply
the result produced by APPEND.
> The second block following append may be empty but must be
> present.
>
APPEND takes two arguments. You can append an empty block to
another block, but you can't omit the second argument entirely.
>> append [1 2 3] []
== [1 2 3]
>> append [1 2 3]
** Script Error: append is missing its value argument
** Near: append [1 2 3]
> Using make in this way seems to be equivalent to:
>
> account: make object! [
> name: make string! 100
> ]
> account: make account [
> balance: $2000
> ]
> account: make account [
> phone: make issue! 10
> state: make string! 2
> ]
>
Exactly. Because the value of the APPEND in your prior code is
>> append [
[ phone: make issue! 10] [state: make string! 2]
== [
phone: make issue! 10 state: make string! 2]
(a single block, which can serve as the spec for MAKE).
> Can someone help me to understand what, why, and/or how
> append is being used in this context? I could find no
> documentation that addresses this point.
>
I have no idea *why* one would APPEND two literal blocks before
supplying them as a spec for MAKE (instead of simply writing
their content as a single block), but I hope the above makes
it more clear *what* is happening:
1) APPEND constructs a block from two blocks.
2) MAKE uses that result as the spec argument when creating
a new object, based on the old value of ACCOUNT as its
prototype.
3) ACCOUNT is set to refer to that new object.
AFAICT, you can use any expression that constructs a correctly-
formed block to supply the second (spec) argument to MAKE. e.g.:
>> account: make object! [
[ name: make string! 100
[ ]
>> account: make account [
[ balance: $2000
[ ]
>> account: make account reduce [
[ to-set-word "phone" 'make 'issue! 5 + 5
[ to-set-word "state" 'make type? "foo" 1 + 1
[ ]
>> source account
account:
make object! [
name: ""
balance: $2000.00
phone: #
state: ""
]
That just happens to be a particularly awkward way to do it! ;-)
-jn-
------------------------------------------------------------
Programming languages: compact, powerful, simple ...
Pick any two!
joel'dot'neely'at'fedex'dot'com