Previously discussed:
>>> But I (personally) don't think it is a good practice to use
>>> nontransparent argument passing anywhere and don't see any
>>> advantages of doing it. (nice flame bait, isn't it?)
>>>       
>
>   
>> Excellent flame bait! :) I think the perceived advantage may have
>> been usability, in not having to remember to use a lit-word! value.
>> Of course, SET and GET require it, as do a few others.
>>     
>
> I strongly agree with Ladislav, personally I dislike "nontransparent
> argument passing" [1] in most of the cases. Personally I find it to be
> of value in much used "console tools" such as 'source or 'help. In
> most other functions I find it far more intuitive to that if a
> function needs a literal word (a symbol) for something to actually
> pass it a lit-word!. The same goes for higher-order functions which
> take a function as an argument.
>
> That's why I prefer
>
>   collect 'emit [ ... ]
>
> over
>
>   collect emit [ ... ] .
>
> Intuitively I see this the following way: the function 'collect needs
> a label to use for a function it provides to the code-block passed as
> second argument. So passing it a lit-word! is more natural and more
> self-documenting in my opinion.
>
> A reader stumbling over "collect emit [ ... ]" would have to know that
> 'collect is a function taking two arguments and that the first
> argument is treated specially (a "lit-argument"). A reader not aware
> of the details of 'collect could also assume that the second line
> calls the function 'emit with a block! and calls the function 'collect
> with the value returned from the 'emit call.
>
>
> [1] I hope that really is the same as what I have in my mind as
> "get-arguments" (:arg) and "lit-arguments" ('arg) :)
>
>   

I wrote an article on the subject in hope, that it might be of some use. 
Here is the first version. Feedback/improvements welcome as usual:

REBOL Argument Passing

    Author: Ladislav Mecir
    Date: 18-May-2006/13:18:02+2:00

===References

Ladislav's articles page is at <a href="index.html">Rebol Articles</a>, 
where you can find other useful references too.

===Referentially Transparent Argument Passing

Joel Neely in one of his REBOL Mailing List posts defined it as the 
ability of a function to take the result of an expression as the 
argument value. I will use his terminology here and call the "normal" 
argument passing "Referentially Transparent Argument Passing". Example:

    f: func [value [any-type!]] [value]
    f 1 + 2 ; == 3

Referential transparency causes, that even a cousin of the above 
function called DTTO and looking too trivial to be useful at the first 
sight, is successfully used in my implementation of the <a 
href="build.r">BUILD dialect</a>.

Another way how to characterize the Referentially Transparent Argument 
Passing is the citation from the REBOL/Core User's Guide: "...the 
interpreter evaluates the arguments of function and passes them to the 
function body..."

---Usage

All REBOL functions except for only a few use this argument passing method.

---Advantages

Referential Transparency - a result of an expression can be supplied as 
an argument value.

Readability - because this method is standard, every "transparent" 
script, i.e. script using just this argument passing method is more 
readable than a "nontransparent" script, i.e. a script using "mixed" 
argument passing.

---Disadvantages

This method does not have any substantial disadvantages.

===Nontransparent Argument Passing

In addition to the above argument passing methods REBOL implements two 
referentially nontransparent argument passing methods (see <a 
href="http://www.rebol.com/docs/core23/rebolcore-9.html";>Argument 
Passing</a> in REBOL/Core User's Guide).

#Literal Argument Passing

#Get Argument Passing

===Literal Argument Passing

The REBOL/Core User's Guide specifies Literal Argument Passing as 
follows: "To specify that an argument not be evaluated, precede the 
argument name with a single quote (indicates a literal word)."

The above specification suggests, that Literally Passed Arguments are 
not evaluated, but that is not true in all situations, see the example:

    ; specify a function g taking an argument value literally
    g: func ['value [any-type!]] [probe :value]
    x: 1
    ; in the following case the argument isn't evaluated:
    g x ; == x
    ; in the following case the argument *is* evaluated:
    g :x ; == 1

---Usage

The following natives/mezzanines use Literal Argument Passing: HELP, 
SOURCE, SECURE, FOR, FOREACH, REPEAT, FORSKIP, FORALL, REMOVE-EACH.

---Advantages

This method is promoted by the REBOL/Core User's Guide as the method to 
use "For instance, if you need to pass a word and access it from the 
function body, you do not want it evaluated as an argument."

This example is false, because e.g. the GET function while designed 
mainly to take a WORD argument does not use Literal Argument Passing 
because Literal Argument Passing isn't referentially transparent above all.

---Disadvantages

The main disadvantage is the nontransparency, i.e. the fact, that you 
cannot use a result of an experession as an argument value.

Another disadvantage is the fact, that the method is inconsistent, 
because it evaluates some argument values as has been demonstrated 
above, so you cannot use it in case you really wish no value to be 
evaluated.

In case of the SECURE function above the usage of Literal Argument 
Passing is not convenient.

Even in case of cycle functions and HELP the convenience is quite 
questionable, because it restricts the usage. (E.g. somebody may wish to 
obtain a help or a source for a result of an expression.)

Readability - no script (known to me) uses just this argument passing 
method, so every script using this method is a "mixed" script using at 
least two argument passing methods and therefore it is less readable.

===Get Argument Passing

The REBOL/Core User's Guide specifies Get Argument Passing as follows: 
"...rather than passing a word, the value of the word is passed without 
being evaluated..."

As opposed to the Literal Argument Passing we may say, that every 
argument is "evaluated", but the "evaluation" is specific for this 
argument passing method.

---Usage

No native/mezzanine uses this argument passing method, which may be 
taken as a sign that the usability is low.

Since the REBOL/Core User's Guide specification holds, I found out, that 
this method is useful in case, when I have got a block of words and need 
to supply the values of the words to a function as its arguments. This 
is why I used the method in my implementation of the CLOSURE function. 
The CLOSURE function can be (and originally was) implemented without the 
Get Argument Passing, but this implementation is both faster and 
simpler. This usage becomes superfluous in R3 anyway, because CLOSURE is 
going to be implemented natively. Even in case CLOSURE wasn't 
implemented natively a kind of the APPLY function (e.g. the APPLY used 
in the REBCODE dialect) taking a block of words would be more than 
adequate replacement for the above mentioned usage of the Get Argument 
Passing method.

---Advantages

See the Usage section above.

---Disadvantages

Nontransparency.

Readability - no script (known to me) uses just this argument passing 
method, so every script using this method is a "mixed" script using at 
least two argument passing methods and therefore it is less readable.

===Argument Passing in General

While I don't think that nontransparent argument passing has got 
sufficiently many advantages, I wrote a function which is able to pass 
arguments to a function using any argument passing method as well as 
take care of refinements etc. The function is called <a 
href="pass-args.r">PASS-ARGS</a>.

The End



-- 
To unsubscribe from the list, just send an email to 
lists at rebol.com with unsubscribe as the subject.

Reply via email to