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

The complete Rebol named argument passing

 [1/23] from: lmecir:mbox:vol:cz at: 26-Feb-2004 9:59


I wrote a function, that can create a block handling complete Rebol named argument passing. (i.e. values, refinements, "normal" arguments, fetched arguments and "unevaluated" arguments) The function supposes, that there is a context containing all locals of the function which refer to the values and refinements that shall be passed. I will be grateful for any tests, optimizations and improvements. Sample test: f: func ['x [any-type!]] [type? get/any 'x] b: pass-args 'x [] :f x: 1 do b ; == integer! unset 'x do b ; == unset! the function: comment [ ; the Pass-args function result ; looks as follows: [ path: to path! 'fn call: make block! 4 + length? prefix insert call prefix insert/only tail call path ; "unevaluated argument passing goes here ; ... ; args are "corresponding" argument values insert tail call args ; here goes refinement handling ; ref is a refinement if ref [ insert tail path 'ref insert tail call args ] ; ... do call ] ] pass-args: function [ {Compose a block passing arguments and refinements to the given function} context [word!] prefix [block!] f [any-function!] ] [item item2 args result result2] [ ; the result shall have its own 'fn, 'path and 'call variables use [fn path call] [ ; 'fn variable shall refer to the function fn: :f ; the ARGS block collects arguments for CALL args: make block! 0 result: copy [ path: to path! 'fn call: make block! 4 + length? prefix insert call prefix insert/only tail call path ; here is the place to handle "unevaluated" arguments ] result2: compose [ insert tail call (reduce [args]) ; here goes refinement handling ] parse first :f [ any [ set item word! ( ; normal argument passing item: bind to lit-word! item context insert tail args compose [get/any (:item)] ) | set item refinement! ( ; refinement handling item: bind to word! item context insert tail call (reduce [args]) ; create "fresh" argument block args: make block! 0 insert tail result2 compose/deep [ if (item) [ insert tail path (to lit-word! item) insert tail call (reduce [args]) ] ] ) | set item lit-word! ( ; "unevaluated" argument passing item: bind :item context item2: bind to get-word! :item context insert p: tail args none insert tail result compose/deep [ change (reduce [p]) either value? (:item) [ ; this handles any value except unset! type (item2) ] [ ; this handles unset! type value ] ] ) | set item get-word! ( ; "fetched" argument passing item: bind to word! item context insert tail args item ) | skip ] ] compose [(result) (result2) do call] ] ] p.s. (for Romano and Gabriele) this can be used as the basic part of SUBFUNC. It substitutes PREPARE-AR and makes FUNCALL unnecessary.

 [2/23] from: lmecir:mbox:vol:cz at: 26-Feb-2004 12:17


hi, there is a bug in the code I posted. I decided to put the repaired code to the REP site: http://www.compkarori.com/vanilla/display/pass-args.r for everyone to be able to access it. -L

 [3/23] from: rotenca:telvia:it at: 26-Feb-2004 14:11


Hi Ladislav, all this stuff about arguments passing is very interesting for me, but remain always too complex for real usage. I think that is a need to change something about this stuff at native level. Do you have some ideas about new native, new syntax to make refinements and/or argument pass more easy? I have the start of an idea: all function should accept argument in the normal way and in a different way: with a block of arguments Example: x: func [a /b c][] ;can be called x/b 1 2 ;or x/arg_block [1 /b 2] perhaps this is not a valid solution, i did not think to it very much, or perhaps there are more valid solutions, i should like to know any opinion If we reach a valid solution we could do a proposal for Carl. --- Ciao Romano

 [4/23] from: g:santilli:tiscalinet:it at: 26-Feb-2004 14:55


Hi Romano, On Thursday, February 26, 2004, 2:11:58 PM, you wrote: RPT> x: func [a /b c][] RPT> ;can be called RPT> x/b 1 2 RPT> ;or RPT> x/arg_block [1 /b 2] I think we just need an APPLY native function, apply :x [1 /b 2] or even: apply :x [1 true 2] that is probably closer to what REBOL does internally. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [5/23] from: rotenca:telvia:it at: 26-Feb-2004 17:46


Hi Gabriele,
> RPT> x: func [a /b c][] > RPT> ;can be called
<<quoted lines omitted: 6>>
> apply :x [1 true 2] > that is probably closer to what REBOL does internally.
How can an apply function understand that true is the /b refinement? Refinement have not an order, like arguments. --- Ciao Romano

 [6/23] from: g:santilli:tiscalinet:it at: 26-Feb-2004 18:21


Hi Romano, On Thursday, February 26, 2004, 5:46:20 PM, you wrote: RPT> Refinement have not an order, like arguments. They do, the order in which they are defined in the function. f: func [a b c] [...] apply :f [1 2 3] it's like set [a b c] [1 2 3] f: func [a /b c] [...] apply :f [1 2 3] it's like set [a b c] [1 2 3] To avoid problems with some function maybe APPLY could accept only LOGIC! values for refinements... Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [7/23] from: rotenca:telvia:it at: 26-Feb-2004 18:56


Hi Gabriele,
> RPT> Refinement have not an order, like arguments. > > They do, the order in which they are defined in the function. >
Yes, but in Rebol this order is not important, while is important the arguments order, so it seems to me a wrong mode to extend the language, also because: find/skip a b 3 should become: find a b false false false false false true 3 omitting arguments for false refinements, else it should become something like: apply :find [find a b false false false false false false false true 3] using the refinements names, it become apply :find [a b /skip 3] which is a little more readable. What means? apply :find [a b false false false false false false false false false false false false true] Solution: find/reverse a b or in the alternative syntax: apply :find [a b /reverse] --- Ciao Romano

 [8/23] from: g:santilli:tiscalinet:it at: 26-Feb-2004 23:40


Hi Romano, On Thursday, February 26, 2004, 6:56:08 PM, you wrote: RPT> omitting arguments for false refinements, else it should become something RPT> like: RPT> apply :find [find a b false false false false false false false true 3] Do you think you would use APPLY that way? I wouldn't. I would use it this way, instead: my-find: func [ series value /part range /only /case /any /with wild /skip size /match /tail /last /reverse ] [ ; something useful ... apply :find [ series value part range only case any with wild skip size match tail last reverse ] ; something useful ... ] Now, if you consider that that block can be constructed automatically, you see that is not so much of a problem. Also, if you have a native APPLY like the one I described, you could write a mezzanine function like the one you described; however, with your APPLY, you'd have trouble writing a function like the above... Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [9/23] from: rotenca:telvia:it at: 27-Feb-2004 0:19


Hi Gabriele,
> Do you think you would use APPLY that way? I wouldn't. I would use > it this way, instead: > apply :find [ > series value part range only case any > with wild skip size match tail last reverse
This is the only case in which you syntax has some advantage. But i think that it is not enough to change an aspect of rebol language: order of refinements must remain not important under any respect. I think that another solution, if any, must be found. --- Ciao Romano

 [10/23] from: g:santilli:tiscalinet:it at: 27-Feb-2004 10:12


Hi Romano, On Friday, February 27, 2004, 12:19:24 AM, you wrote:
>> Do you think you would use APPLY that way? I wouldn't. I would use >> it this way, instead: >> apply :find [ >> series value part range only case any >> with wild skip size match tail last reverse
RPT> This is the only case in which you syntax has some advantage. This is the only case I would use APPLY for --- passing arguments and refinements from another function. If the block you pass APPLY is not constructed programmatically, then you don't need APPLY at all. But if it is, having everything in the same order as in the function spec is much simpler. RPT> But i think that it is not enough to change an aspect of rebol language: order RPT> of refinements must remain not important under any respect. I don't see why having such an APPLY would change this... Anyway, I think Ladidlav's APPLY can be taken as a prototype. Probably, its /N refinement would make everyone happy. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [11/23] from: rotenca:telvia:it at: 27-Feb-2004 11:46


Hi Gabriele,
> This is the only case I would use APPLY for --- passing arguments > and refinements from another function. If the block you pass APPLY > is not constructed programmatically, then you don't need APPLY at > all. But if it is, having everything in the same order as in the > function spec is much simpler.
The only case of which i am speaking is the case you show: a function which call another function with the same context/refinements (a patch). Instead, if i have a function like this: my-func: [a b /skip value /reverse] and i want to pass /reverse to find, I must construct exactly that kind of block full of false which seems so strange to you and that you say you will never use.
> But if it is, having everything in the same order as in the > function spec is much simpler.
It is a solution, i do not negate it. Only, i do not like it.
> RPT> But i think that it is not enough to change an aspect of rebol
language: order
> RPT> of refinements must remain not important under any respect. > > I don't see why having such an APPLY would change this...
If i rewrite a function i must respect the refinements order to make old program not fail. --- Ciao Romano

 [12/23] from: g:santilli:tiscalinet:it at: 27-Feb-2004 12:28


Hi Romano, On Friday, February 27, 2004, 11:46:59 AM, you wrote: RPT> Instead, if i have a function like this: RPT> my-func: [a b /skip value /reverse] RPT> and i want to pass /reverse to find, I must construct exactly that kind of RPT> block full of false which seems so strange to you and that you say you will RPT> never use. Hmm, but if you have to construct the block, then why not constructing a path like Ladislav does in his functions. I don't see any advantage. RPT> If i rewrite a function i must respect the refinements order to make old RPT> program not fail. Probably it's much better to use named arguments then. Otherwise Carl has to add binding to refinements too. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [13/23] from: rotenca:telvia:it at: 27-Feb-2004 15:38


Hi Gabriele,
> Hmm, but if you have to construct the block, then why not > constructing a path like Ladislav does in his functions. I don't > see any advantage.
I don't understand. The apply function was a your propose. --- Ciao Romano

 [14/23] from: g:santilli:tiscalinet:it at: 27-Feb-2004 16:04


Hi Romano, On Friday, February 27, 2004, 3:38:50 PM, you wrote: RPT> I don't understand. RPT> The apply function was a your propose. I mean, that if you have to do something like: args: [1 2] if reverse [append args /reverse] if skip [repend args [/skip amount]] apply :find args then a native APPLY is useless, as you doing the same amount of work that Ladislav's function does. That's why I don't like your proposed APPLY. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [15/23] from: rotenca::telvia::it at: 27-Feb-2004 18:10


> I mean, that if you have to do something like: > args: [1 2]
<<quoted lines omitted: 3>>
> then a native APPLY is useless, as you doing the same amount of > work that Ladislav's function does.
Ah, yes. It could be: apply :find [/reverse true] apply :find [/reverse false]
> That's why I don't like your proposed APPLY.
I don't want an Apply. I should like or a special /refinement or a function like 'do to prepend. do-alt find /reverse false find/alt /reverse false --- Ciao Romano

 [16/23] from: g:santilli:tiscalinet:it at: 27-Feb-2004 18:39


Hi Romano, On Friday, February 27, 2004, 6:10:28 PM, you wrote: RPT> I don't want an Apply. RPT> I should like or a special /refinement or a function like 'do to prepend. RPT> do-alt find /reverse false RPT> find/alt /reverse false You can't have that, the best we could get is: find/alt [/reverse false] but, personally, I don't like it. The best option seems to be like Ladislav suggests, apply :find [reverse: true series: [a b c] value: 'd] Requires a bit more work when you are just propagating arguments, but it's better in other cases. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [17/23] from: rotenca:telvia:it at: 1-Mar-2004 16:19


Hi Gabriele
> RPT> do-alt find /reverse false > > RPT> find/alt /reverse false > > You can't have that, the best we could get is:
I think that both are possible. I prefer the first one.
> The best option seems to be like Ladislav suggests, > > apply :find [reverse: true series: [a b c] value: 'd] > > Requires a bit more work when you are just propagating arguments, > but it's better in other cases.
Better than nothing, but not the best. --- Ciao Romano

 [18/23] from: g:santilli:tiscalinet:it at: 1-Mar-2004 17:03


Hi Romano, On Monday, March 1, 2004, 4:19:32 PM, you wrote:
>> RPT> do-alt find /reverse false >> >> RPT> find/alt /reverse false >> >> You can't have that, the best we could get is:
RPT> I think that both are possible. I prefer the first one. There's no way to do that, REBOL needs to know the number of arguments to process BEFORE actually starting to collect them. Even if you were going to change the interpreter to allow something like that, you'd have two issues: 1) ambiguity and 2) not being expression based anymore. Ambiguity: f: func [x /ref] [...] g: func [x /ref] [...] f g x /ref Does /ref belong to F or G? You need to parenthesize all expressions. No more expression based: f x either cond [/ref] [none] would you expect this to work? If not, your proposal is useless, as you can't propagate refinements anyway. If yes, you have no way to know that you have to evaluate the next expression without knowing that it will return a REFINEMENT! value. If you evaluate it and it does not return a refinement, you have evaluated the expressions in the wrong order. If you don't and it would have returned a refinement you are calling the function without all arguments. To solve this you'd need to parenthesize all expressions. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [19/23] from: maximo:meteorstudios at: 1-Mar-2004 11:25


> To solve this you'd need to parenthesize all > expressions.
NNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!! picture a man diseapearing away in a vortex, screaming while looking up at the camera in a bad horror movie... ;-) I'm starting to find that discussion a little bit sterile. Sorry if I seem negative... but it seems that you guys are trying to change something in rebol which isn't yet broken! Every suggestion seems to break this or that intrinsic rebol rule. Am I way off track? If so tell me to shut up ;-) -MAx

 [20/23] from: g:santilli:tiscalinet:it at: 1-Mar-2004 17:50


Hi Maxim, On Monday, March 1, 2004, 5:25:10 PM, you wrote: MOA> I'm starting to find that discussion a little bit MOA> sterile. Sorry if I seem negative... but it seems that you MOA> guys are trying to change something in rebol which isn't yet MOA> broken! I *DON'T* want to change REBOL, that's why I'm saying that Romano's proposal does not make sense. :-) We just need a native implementation of Ladislav's named-apply. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [21/23] from: rotenca:telvia:it at: 1-Mar-2004 18:18


Hi Gabriele,
> arguments. To solve this you'd need to parenthesize all > expressions.
Yes. The do-alt function could have some limitations not present in the standard evaluation routine. But now I have another proposal, with less problems (I hope): a: "abcd" b: "c" case: true skip: true size: 2 do-alt find/case/skip a b size the interpreter fetch the path (find/case/skip) and checks every word in it: 'case if none/false => refinement /case is false else => refinement /case is true 'skip if none/false => refinement /skip is false (size argument will be ignored) else => refinement /skip is true => size argument required My doubt is about the size argument when the refinement is none: must be omitted or it will be ignored (not evalutaed but skipped)? In the latter case we can write: my-func: func [a b /case /skip size ][ do-alt find/case/skip a b size ] also if /skip is none, else we must manually check the skip value in my-func before calling find. I already have working mezzanine versions using a block, but i should like to have a do-alt native. --- Ciao Romano

 [22/23] from: antonr:iinet:au at: 3-Mar-2004 16:01


This sparks an idea for new syntax for me. How about: find/::case/::skip a b size That way you can pick and choose which refinements will be propagated and which are hard-coded. eg: find/::case/skip a b size This means: /case is propagated if case is true /skip is always specified Anton.

 [23/23] from: rotenca:telvia:it at: 3-Mar-2004 16:47


Hi Anton,
> This sparks an idea for new syntax for me. How about: > find/::case/::skip a b size
<<quoted lines omitted: 4>>
> /case is propagated if case is true > /skip is always specified
Interesting, but this should require a new word datatype double-get-word!. --- Ciao Romano

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted