Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: variable number of arguments

From: al:bri:xtra at: 28-Nov-2000 21:29

> > >> fget: func [:a][probe :a] > > >> fget 1 + 2 > > 1 > > == 3 > > > > Why did "1" get printed? And why was the result of 3 printed _after_ the
1 ?
> LM> I think, that the explanation of the above can be pretty simple:
function Fget asks for its argument to be fetched, which means, that no 1 + 2 calculation is allowed *before* supplying an argument to Fget. That is why the evaluation of the addition is *postponed* here until Fget is evaluated. Let's make sure:
> make-sure3: func [:a] [2 * probe :a] > make-sure3 1 + 2 > 1 > == 4
While that argument seems to fit, it doesn't fit the fact that there's no do involved? Functions don't need to ask "do" to evaluate themselves, they actively get their own arguments, when they're evaluated.
> AM> > > Here's another function: > > feval: func [a][probe :a] > > Note that I've dropped one colon out in the "function spec".
Therefore 'a is evaluated. Here's the Rebol console session:
> > > > >> feval: func [a][probe :a] > > >> feval 1 + 2 > > 3 > > == 3 > > > > Note that both cases, the line: > > probe :a > > never evaluates 'a. So where does 'a get evaluated? Effectively
here:
> > func [a] > > More exactly, 'a is evaluated inside the brackets after "func". Or
perhaps better to say that an evaluated argument in a function processes or evaluates the input stream of values until a natural stopping point is reached. In other words, the input stream reduces down to a value that is not a func or prefix operator (effectively a function) and isn't a value followed by a binary operator value. The input stream of values is also terminated by the presence of a right square bracket. Because continuations , IIRC, aren't in Rebol, the function argument evaluation mechanism can't "leap out" of the function body and resume processing the upper or "outer" level input stream of values.
> LM> Here, as opposed to your previous example, the evaluation of the
Feval's argument is allowed *before* Feval gets it, that'a all. No "inside brackets" evaluation is needed to explain the difference. No, the function just evaluates it's own arguments as specfied by it's function spec. There's no need for the function to ask an external evaluation system to do it.
> AM> > > So the error message: > > > > ** Script Error: f is missing its a1 argument > > ** Where: make-sure1 > > ** Near: f > > > > means what it says, and 'do only has one argument. > > > > I hope that helps! > LM> It doesn't help, because you didn't succeed to explain, why you aren't
able to write a Rebol function similar to Make-sure4:
> make-sure4: func [ > {This function takes five arguments} > f a2 a3 a4 a5 > ][ > ; evaluate f > f :a2 :a3 :a4 :a5 > ] > > , but able to take any function (not only a function having at most four
arguments) and evaluate it correctly. You can if you delay evaluation until the function is in the same context as it's arguments:
>> do func [a b c][print [a + 10 b + 20 c + 30]] 1 2 3
11 22 33 which is effectively what your function 'take-n simplifies down to.
> FYI my explanation is, that if such a hypothetical function had to
evaluate its first argument correctly, it should have supplied it all necessary arguments, but that is not possible, because the only Rebol function capable of doing that is currently the Do function. 'do doesn't do that. It only seems to.
> This subject has something in common with Rebol orthogonality, where we
see, that Rebol, using itself a function capable of taking a variable number of arguments, doesn't allow a user to define such a function routinely too. The interesting thing about that is, that such functions can be added to Rebol without *any* difficulty, because such functions basically do the same as the functions taking a block as their only argument. Here's how 'do works for the example above. Rebol evaluates 'do. 'do requires one arguement and evaluates it's one argument, the 'func word (which happens to be next at the "instruction pointer"). 'func evaluates it's two arguments, the spec and body blocks, and returns itself as a function! datatype. (The input "instruction pointer" is now at the start of the "1 2 3" sequence. 'do sees the function! datatype and evaluates the function! datatype again. The function checks out its spec "[a b c]" and evaluates the "1 2 3" in succession (advancing the "instruction pointer" successively) and assigns the values to "a b c" then evaluates it's function body (print "11 22 33"), returning the last result in the block to 'do, which is unset!, which the console won't display.
> Thanks for the interesting discussion on the subject, I hope, that it
wasn't boring for anybody. It's been interesting. I had to really think about it. Reminded me of programming in Intel 8085 machine code and Motorola 6809 assembler, but this was a lot easier. Andrew Martin Rebol assembler! ICQ: 26227169 http://members.nbci.com/AndrewMartin/