[REBOL] Re: ROUND function (like TRUNC, FLOOR, etc...)
From: joel:neely:fedex at: 21-Feb-2002 9:31
Hi, Gabriele,
Gabriele Santilli wrote:
> At 20.59 20/02/02, you wrote:
>
> >Functions have context. Does that mean that functions have objects?
> >I wouldn't even have a problem with the statement "An object *is*
> >A KIND OF context"...
>
> Well, I'd say that an OBJECT! is a wrapper around a CONTEXT! (which
> is not exposed at the language level).
>
Yes. But that wrapper is important (and a distinct idea) because REBOL
can do things with objects that it doesn't appear (in general) to do
with contexts.
> So the relationship between OBJECT! and CONTEXT! is rather tight;
> you can view a OBJECT just as a "named context" if you want.
>
> But I think the reason for calling that function 'CONTEXT is
> different. What is the simplest way to make a context?
>
I can think of at least two simple ways:
>> use [counter] [
[ counter: 0
[ counter-reset: func [] [counter: 0]
[ counter-up: func [] [counter: counter + 1]
[ counter-down: func [] [counter: counter - 1]
[ ]
>> counter-up
== 1
>> counter-up
== 2
>> counter-up
== 3
>> counter-up
== 4
>> counter-down
== 3
>> counter-down
== 2
>> counter-reset
== 0
>> countobj: make object! [
[ counter: 0
[ reset: func [] [counter: 0]
[ up: func [] [counter: counter + 1]
[ down: func [] [counter: counter - 1]
[ ]
>> countobj/up
== 1
>> countobj/up
== 2
>> countobj/up
== 3
>> countobj/up
== 4
>> countobj/down
== 3
>> countobj/down
== 2
>> countobj/reset
== 0
It seems to me that these are equally simple to write and use as long
as I only need one counter. What I gain by using an object instead
of an anonymous scope is the ability to ask REBOL to "make me another"
whenever I want.
Another way to create a context (admittedly not quite as simple, but
IMHO almost so) would be:
>> countfunc: func [/reset /up /down /local counter] [
[ counter: [0]
[ if reset [change counter 0]
[ if up [change counter counter/1 + 1]
[ if down [change counter counter/1 - 1]
[ counter/1
[ ]
>> countfunc/up
== 1
>> countfunc/up
== 2
>> countfunc/up
== 3
>> countfunc/up
== 4
>> countfunc/down
== 3
>> countfunc/down
== 2
>> countfunc/reset
== 0
Minor differences in simplicity aside, each of these cases creates
a context and provides an interface to manipulate the state of that
context.
If REBOL were ever enhanced to expose contexts as first-class values,
we might be able to do useful things like:
1) ask for the context of a specific word;
2) use a context as the explicit second argument to BIND;
3) use a context as the first argument of IN;
4) be able easily to ask whether two words belonged to the
same context;
5) ask whether a specific word belonged to a specific context;
and so on ... Making contexts first-class would be consistent with
the REBOL approach that "everything is just a value" and would likely
help de-mystify some of the more interesting things that REBOL can do
that can't even be *said* in some other languages.
A nice notation for (1) would be
context some-word
except that CONTEXT is now in use as a fairly trivial shortcut.
We certainly couldn't say
context? some-word
because (at least if there's going to be some semblance of consistency)
that would be asking whether SOME-WORD is a value of type CONTEXT!
instead. That leaves us with something like
get-context some-word
which isn't too horrible, I guess, but the opportunity for confusion
remains because the value of
context some-block
would be of OBJECT! and not CONTEXT! type.
I know that I'm talking about hypotheticals when thinking about
context as a first-class type. However, the *concept* of context
seems to me very important in understanding how REBOL behaves.
I simply think that anything that muddles up our terminology makes
explaining/learning REBOL harder than necessary.
-jn-