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

nargs

 [1/8] from: maarten::vrijheid::net at: 17-Oct-2003 11:53


Here is a nargs function that also counts the optional arguments if you use refinements (e.g. nargs copy == 1 nargs copy/part == 2). Enjoy it. ----------------------------------- nargs: func [ {Returns the total number of args of a function (with and without refinements)} f [word! lit-path!] /local argc f-blk f-ref f-sig ref-pos next-ref-pos ] [ ;The total number or arguments argc: 0 ;We either have a path or a function ;If we have a path, we count the number ;of arguments of the supplied refinements first. either path? f [ ;Translate the path to a block f-blk: to-block f ;Is it a function? if not any-function? get/any first f-blk [throw make error! "Rugby error: invocation not on a function"] bind f-blk 'do ;The refinements used f-ref: next head f-blk ;the function signature f-sig: first get first f-blk ;Now get the number of arguments foreach refinement ;and add them to argc repeat ref f-ref [ ;Find the ref refinement ref-pos: find/tail f-sig to-refinement ref ;If succeed in the find if not none? ref-pos [ ;try to find the next one next-ref-pos: find ref-pos refinement! if not none? next-ref-pos [ argc: argc + ((index? next-ref-pos) - (index? ref-pos)) ];if not none next-ref-pos ];if not none? ref-pos ];foreach ref f-ref ];either path? f first clause [ if not any-function? get/any f [ throw make error! "Rugby error: invocation not on a function" ] f-sig: first get f ];either path? f second clause ;Add the number of function arguments argc: argc + -1 + index? any [ find f-sig refinement! tail f-sig ] ];nargs

 [2/8] from: AJMartin:orcon at: 24-Dec-2003 22:41


Maarten wrote:
> Here is a nargs function that also counts the optional arguments if you
use refinements (e.g. nargs copy == 1 nargs copy/part == 2).
> [Snip large chunk of code.]
Ouch! That's a large amount of code. Isn't this easier?
>> length? Arguments :copy
== 1
>> source Arguments
Arguments: func [ {Returns the arguments of the function as a block of word! values.} F [any-function!] "The Function" ][ head clear any [ find first :F refinement! tail first :F ] ] And if one needs the length of a path:
>> length? 'copy/part
== 2 Or perhaps I've misunderstood something? Andrew J Martin Grail Jedi ICQ: 26227169 http://www.rebol.it/Valley/ http://valley.orcon.net.nz/ http://Valley.150m.com/

 [3/8] from: cyphre:seznam:cz at: 17-Oct-2003 13:02


Hi Maarten, Not sure if this is better/complete solution version but I just hacked for fun simmilar function with the same functionality and it also proper counts the /local words ;-) example:
>> nargs 'copy
== 1
>> nargs 'copy/deep
== 0
>> nargs 'copy/part
== 1
>> nargs 'copy/local
== 0
>>
--------------------start of code-------------------------- nargs: func [f [word! path!] /local loc? ref? args refs fn rf][ fn: either word? f [ get f ][ rf: to-refinement first next to-block f get first f ] args: copy [] refs: copy [] parse third :fn [ any [ set w word! ( either ref? [ insert tail last refs w ][ insert tail args w ] ) | m: refinement! ( ref?: true insert tail refs reduce [m/1 copy []] ) | skip ] to end ] return either rf [ length? any reduce [select refs rf []] ][ length? args ] ] -------------------end of code-------------------------------- enjoy it, Cyphre

 [4/8] from: maarten:vrijheid at: 17-Oct-2003 13:18


Nargs returns the actual number of arguments depending upon your invocation: e.g. nargs 'open/lines or nargs 'open/lines/binary etc. with "object" detection. As you can see it is a Rugby excerpt. --Maarten

 [5/8] from: maarten:vrijheid at: 17-Oct-2003 14:41


> >> nargs 'copy/deep > == 0
?? --Maarten

 [6/8] from: cyphre:seznam:cz at: 17-Oct-2003 16:04


Ups, posting in hurry brings always bugs ;) Here is the fixed version: example:
>> nargs 'open
== 1
>> nargs 'open/binary
== 1
>> nargs 'open/binary/mode
== 2
>> nargs 'open/binary/mode/with
== 3
>>
etc. ------------------start of code-------------------- nargs: func [f [word! path!] /local rslt loc? ref? args refs fn rf][ fn: either word? f [ get f ][ rf: copy next to-block f get first f ] args: copy [] refs: copy [] parse third :fn [ any [ set w word! ( either ref? [ insert tail last refs w ][ insert tail args w ] ) | m: refinement! ( ref?: true insert tail refs reduce [m/1 copy []] ) | skip ] to end ] return either rf [ rslt: 0 (length? args) + foreach a rf [ rslt: rslt + length? any reduce [select refs to-refinement a []] ] ][ length? args ] ] ------------------------------end of code----------------------------------

 [7/8] from: maarten:vrijheid at: 17-Oct-2003 16:25


But what if I pass in an object with a function? --Maarten

 [8/8] from: cyphre:seznam:cz at: 19-Oct-2003 22:37


ok here you are a newer version which also takes objects with functions ;) --------------------------------------------start of code--------------------------------- nargs: func [f [word! path!] /local rslt ref? args refs fn rf obj][ rf: copy [] fn: either word? f [ get f ][ rf: get first f either any [block? :rf object? :rf][ rf: copy to-block f repeat n length? rf [ if error? try [do reduce [to-path copy/part rf n]][ obj: do reduce [to-path copy/part rf n - 1] rf: at rf n + 1 break/return get in obj first back rf ] ] ][ rf: copy next to-block f get first f ] ] args: copy [] refs: copy [] parse third :fn [ any [ set w word! ( either ref? [ insert tail last refs w ][ insert tail args w ] ) | m: refinement! ( ref?: true insert tail refs reduce [m/1 copy []] ) | skip ] to end ] return either empty? rf [ length? args ][ rslt: 0 (length? args) + foreach a rf [ rslt: rslt + length? any reduce [select refs to-refinement a []] ] ] ] ----------------------------------------end of code-------------------------------------- cheers, Cyphre