[REBOL] Re: Back to the Advanced Port stuff again
From: rebol:techscribe at: 11-Jan-2001 22:30
Hi Paul,
To make this a little more interesting for you, I've included code that
shows you how you can add the words associated with the ports to the
block, instead of adding the ports themself, so that all ports will be
contained in wait-ports like your irc-open-port. I understand that is
what was troubling you?
you wrote:
> Actually, the waitports is defined as an empty block at the begining of the
> script:
>
> waitports: []
> then later...
> waitports: [irc-open-port]
Do you use the first definition (waitports: []) for any purpose before
it is defined as waitports: [irc-open-port]? If not, note that the first
definition does not accomplish anything.
I assume that at a later point in time you add ports to wait-ports using
the insert or the append function.
1. waitports: []
What happens here is that you are associating the word waitports with an
empty literal block. If you want you can now begin to insert or append
stuff to the block, (or remove and search for appended stuff) and so on.
This literal block will survive as long as the word waitports (or a
different word) are associated with it, or if it is referenced from
within a function, an object, or a block, as long as that function,
block ... is being referenced by a word (chain of references), or itself
is referenced in a block ... which in turn is referenced by a word. As
soon as all "live" references to the literal block are consumed by the
garbage collector (unset 'waitports, for instance) the literal block
will be garbage collected.
2. waitports: [irc-open-port]
a) Now the empty literal block in 1 is no longer bound by waitports, and
it will be garbage-collected (unless there was a previous step in which
the block became associated with some other live value, such as a
difference word, or "live" block ...). The literal block that you just
abandoned will be garbage- collected and with it all its contents, with
exception of stuff that additionally associated with (or bound to) some
other surviving value ...)
b) waitports is now assigned to a block that contains a word. Note that
nothing happens with the word irc-open-port in the block. Most notably
it is not automatically replaced by its value. Therefore, if you probe
the block, the word irc-open-port will be reported as the contents of
the block and not the value that irc-open-port is bound to.
If you subsequently add other ports to the block using insert or append,
the values (and not the words) will be added. A simple example:
>> a: 1 ;- Step 1
>> b: 2 ;- Step 2
>> c: [a] ;- Step 3
>> append c b ;- Step 4
The block in step 3 "protects" the word a that it contains. The word is
not replaced by its value, and the block assigned to c contains the word
a. Note that a does not even have to have been associated with a value.
x: [y] will work, even if y was not previously associated with any
value.
What happens in step 4? The function append is evaluated. This function
expects two arguments, a series type, and some other value. REBOL looks
at the input stream and designates the two tokens following append as
appends arguments. REBOL determins that c is a block, it replaces the
word c by its value, namely the block, and determines that the block c
fulfills append's requirement for a series type value as its first
argument. REBOL needs a second argument for append, and finds the word
b. This word (like c) is replaced by its value (namely 2) and the
integer 2 is passed to append as its second argument. The resulting
block c is
>> c
== [a 2]
The a that was already "packaged" in the block was never evaluated, and
therefore it continues to exist as an unevaluated word. The word b never
reached the block, because it was replaced by its value, 2, before it
was passed to append which inserted 2 (and not b) in the tail of block
c. Therefore the value associated with b, namely 2, is the second
element of the block c.
The same thing is probably happening in your case. When you associate
waitports with the block [irc-open-port] the word irc-open-port is not
evaluated, i.e., it is not replaced by its value, and therefore it the
first element of the block. I think it's understood by now.
So, what do you do in order to have a block waitports which uniformly
contains either ports, or words that evaluate to ports?
1. ... uniformly contains ports:
>> waitports: []
>> insert waitports irc-open-port
In this example irc-open-port is evaluated and its value (the
port-object) will be inserted, not the word itself.
Another option:
>> waitports: reduce [irc-open-port]
The reduce function returns a block in which the word irc-open-port has
been replaced by its value.
2. ... uniformly contains WORDS that evaluate to port objects:
>> waitports: [irc-open-port]
Ok, we know by now that the block protects the word irc-open-port, it is
not evaluated, and therefore the block associated with waitports is
currently
>> waitports
== [irc-open-port]
How about the other ports? Simple. Assuming that you are using the
string "Paul" which identifies the user Paul as set-word! that will be
associated with a port:
>> user: "Paul"
>> word: to set-word! join user "s-open-port"
== Pauls-open-port:
>> word make port-object! [ .... ]
>> append waitports to word! :word
== []
>> probe waitports
== [irc-open-port Pauls-open-port]
Great, now how do you get the port associated with Pauls-open-port?
There are different ways:
>> second reduce wait-orts
>> get second waitports ;- less compute-intensive if you have a lot of ports
>> get waitports/2
>> first find wait-ports 'Pauls-open-port ;- will return the word Pauls-open-port
== Pauls-open-port
>> get first find wait-ports 'Pauls-open-port ;- will get the port associated with Pauls-open-port
But if you don't know that its "Paul" s-open-port? Here:
>> get first find wait-ports to word! join user "s-open-port"
Hope this helps,
Elan