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

Reflectivity: How a function can know its own name ?

 [1/14] from: laplace:worldnet at: 24-Mar-2002 17:36


In rebol doc, it is said that function can know himself (its argument, its code) but I can't see how it can know just its name : it would seem logical that it is the firts thing it should know :) ?

 [2/14] from: joel:neely:fedex at: 24-Mar-2002 13:05


Hi, Laplace, laplace wrote:
> In rebol doc, it is said that function can know himself > (its argument, its code) but I can't see how it can know > just its name : it would seem logical that it is the firts > thing it should know :) ? >
Given a value of type FUNCTION! it is possible to acquire its argument list and body.
>> foo: func [x [integer!] y [string!]] [append/dup copy "" y x] >> first :foo
== [x y]
>> second :foo
== [append/dup copy "" y x]
>> third :foo
== [x [integer!] y [string!]] However... A function doesn't have a name. A function is a value, and zero, one, or more words can refer to that value, but "name" is not an attribute of a function in REBOL. For the sake of analogy, it's like having a reference to a string value and asking for its "name". -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]

 [3/14] from: rotenca:telvia:it at: 24-Mar-2002 20:08


Can be done only when the function is build. You must write a custom 'func function to remember body and args spec. --- Ciao Romano

 [4/14] from: sunandadh:aol at: 24-Mar-2002 15:10


laplace:
> In rebol doc, it is said that function can know himself > (its argument, its code) but I can't see how it can know > just its name : it would seem logical that it is the firts > thing it should know :) ?
the "name" of a function is a problematic concept in Rebol. Take this code, for example: myfunc1: func [] [ print "what's my name?" do func [] [ print "what's _my_ name?" ] ; end unnamed func 0 / 0 ; cause error in myfunc1 ] ; end myfunc1 ;; we've just defined a function "called" myfunc1 that creates and executes ;; an unnamed function on the fly myfunc1 ;; we get an error message saying error in myfunc1. So far, so normal. myfunc2: :myfunc1 myfunc2 ;; But we've now assigned a second name to the function: both ;; myfunc1 and myfunc2 refer to the _same_ definition. myfunc3: do load mold :myfunc1 myfunc3 ;; Unlike this where myfunc3 is a different function same? :myfunc1 :myfunc2 same? :myfunc1 :myfunc3 equal? :myfunc1 :myfunc3 equal? mold :myfunc1 mold :myfunc3 ;; (A little mystery: why are :myfunc1 and :myfunc3 ;; different, but molds of them are equal?) ;; Next: make five copies of the function in a ;; block, and execute one of them. You could ;; argue that the name of the function is ;; myfuncs/5 -- but what if the block had no ;; name? myfuncs: copy [] loop 5 [append myfuncs :myfunc1] myfuncs/5 Sunanda.

 [5/14] from: al:bri:xtra at: 25-Mar-2002 20:38


> In rebol doc, it is said that function can know himself (its argument, its
code) but I can't see how it can know just its name : it would seem logical that it is the firts thing it should know :) ?
>> F1: F2: func [arg] [join "123" arg] >> source f1
f1: func [arg][join "123" arg]
>> source f2
f2: func [arg][join "123" arg] Which word is the function's name? Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [6/14] from: laplace:worldnet at: 26-Mar-2002 19:43


Thanks for your answer. In your examples you show that in SOME cases, the name concept can be a problem. But It would seem logical for me that the system implements an instruction for a function to know its own name when it is possible. This is useful for generic programming with encapsulation style (polymorphism). What I want to do is to be able to have a serie of functions calling within their own context a generic function which will behave differently depending on the name of the caller function. The place and the way each function will call this generic function will vary. Suppose name of self exists for function I could do: generic_function: make function ['function_name] [ print function_name ] func1: make function! [ instruction11 instruction12 generic_function [name of self] instruction13] func2: make function! [generic_function [name of self] instruction21 ] ... func10: make function! [ instruction31 generic_function [name of self]] ---- If I don't have a "name of self" for function, each time I add a new function to call generic function, it is in the code of generic function that I would have to test the name of the function with a more or less gigantic number of test instructions: generic_function: make function ['function_name] [ if function_name = "func1" [ instruction11 instruction12 print function_name instruction13 ] if function_name = "func2" [ print function_name instruction21 ] ]

 [7/14] from: laplace::worldnet::fr at: 26-Mar-2002 19:54


Hello thanks for the code. I will be useful for me since I just began to look at Rebol. Nevertheless my problem is in fact to know the name of the function FROM INSIDE the function because I want to do something like this (see my first anwer to the thread I suppose that an instruction name of self is implemented for rebol function): generic_function: make function ['function_name] [ print function_name ] func1: make function! [ instruction11 instruction12 generic_function [name of self] instruction13] func2: make function! [generic_function [name of self] instruction21 ] ... func10: make function! [ instruction31 generic_function [name of self]] ---- If I don't have a "name of self" for function, each time I add a new function to call generic function, it is in the code of generic function that I would have to test the name of the function with a more or less gigantic number of test instructions: generic_function: make function ['function_name] [ if function_name = "func1" [ instruction11 instruction12 print function_name instruction13 ] if function_name = "func2" [ print function_name instruction21 ] ]

 [8/14] from: carl:cybercraft at: 27-Mar-2002 14:32


On 27-Mar-02, laplace wrote:
> If I don't have a "name of self" for function, each time I add a new > function to call generic function, it is in the code of generic
<<quoted lines omitted: 15>>
> ] > ]
This doesn't address the function name problem, but there is a 'select word in View which would get around the need for multiple 'ifs. ie... item: 'blk-2 do select [ blk-1 [print "a"] blk-2 [print "b"] blk-3 [print "c"] ] item -- Carl Read

 [9/14] from: al:bri:xtra at: 27-Mar-2002 17:11


laplace asked about function names. Here's an alternative solution:
>> functions: reduce [
[ func [x] [print ["I'm the first function!" X]] [ func [y] [print ["Second function!" y]] [ ] == [func [x][print ["I'm the first function!" X]] func [y][print ["Second function!" y]]]
>> generic: func [A F [function!]] [
[ f a [ ]
>> generic 123 pick functions 1
I'm the first function! 123
>> generic 123 pick functions 2
Second function! 123
>>
Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [10/14] from: sunandadh:aol at: 27-Mar-2002 4:05


[laplace--worldnet--fr]:
> Thanks for your answer. In your examples you show that in SOME cases, the > name concept can be a problem. But It would seem logical for me that the > system implements an instruction for a function to know its own name when
it
> is possible.
I agree. I used the term "problematic concept" when referring to the "name" of a function, because it's a problem for Rebol (which often can't tell for reasons already stated), developers (who know when a function has a name, and just want to get hold of it) and support staff (who want precisely pinpointed error information when code fails -- including, of course, the current function name, if there is one). Someone (sorry I can't find the original post to credit you) came up with a method of finding the function name -- if it exists -- by forcing an error and grabbing the 'where value from the error object. This shows that the name of a function -- where it exists -- is available. It's a pity that it isn't more easily accessible. You could always encapsulate the code below into a function-name? word, and then ask RT to make it native for speed, Here's some sample code based on the half-remembered post. You'll see some of the problematic issues for an unnamed function. But if your functions -- like most of mine -- have a name, this may work for you. myfunc1: func [] [ print ["my name is " get in disarm try [0 / 0 ] 'where ] ] myfunc1 ;; name of function identical to func1 myfunc2: :myfunc1 myfunc2 ;; name of function in a block -- various forms myfuncs: copy [] loop 5 [append myfuncs :myfunc1] foreach f myfuncs [f] for nn 1 length? myfuncs 1 [myfuncs/:nn] for nn 1 length? myfuncs 1 [do pick myfuncs nn] myfuncs/4 ;; name of function in an object myobj: make object! [objfunc: ""] myobj/objfunc: :func1 myobj/objfunc Sunanda

 [11/14] from: rotenca:telvia:it at: 27-Mar-2002 15:13


There are no direct modes, but you could 1) use an hack (look at this thread http://www.escribe.com/internet/rebol/m18105.html) 2) writing the func to be aware of itself (not of its name), with something like this:
>> use [self][ext-name: self: func [][print ["mycode is:" mold second
:self]]]
>> ext-name
mycode is: [print ["mycode is:" mold second :self]] You can do a new func type function with something like: reflex-func: func [spec body][ use [self] [self: func spec bind body 'self]] to use in this mode:
>> f: reflex-func [][print mold second :self] >> f
== [print mold second :self] or you can use the name 'func itself hidden in a context: ob: context [func: system/words/func [spec body][ use [self] [self: system/words/func spec bind body 'self]]] then: do bind [ f1: func [][print mold second :self] f2: func[] [print 7] ] in ob 'self
>> f1
[print mold second :self]
>> f2
7 (i have not tested deeply the code) --- Ciao Romano

 [12/14] from: lmecir:mbox:vol:cz at: 27-Mar-2002 17:37


Hi Laplace, I will try to give you an exhaustive answer: a) Rebol functions are anonymous, i.e. they do not have names, although you can set any Rebol word to refer to any Rebol function b) it is easy to do what you described, there is a whole lot of ways how to program that in Rebol: b1) generic-function: func [function-name [word!]] [ do get function-name function-name ] func1: func [function-name [word!]] [ instruction11 instruction12 print function_name instruction13 ] func2: func [function-name [word!]] [ print function_name instruction21 ] b2) another possibility is to use the error handling mechanism as described by Carl b3) it is easy to make your own functions that do have a name attribute (I can explain how, if you really need it) etc. Cheers L ----- Original Message ----- From: "laplace" To: <[rebol-list--rebol--com]> Sent: Tuesday, March 26, 2002 7:54 PM Subject: [REBOL] Re: Reflectivity: How a function can know its own name ? Hello thanks for the code. I will be useful for me since I just began to look at Rebol. Nevertheless my problem is in fact to know the name of the function FROM INSIDE the function because I want to do something like this (see my first anwer to the thread I suppose that an instruction name of self is implemented for rebol function): generic_function: make function ['function_name] [ print function_name ] func1: make function! [ instruction11 instruction12 generic_function [name of self] instruction13] func2: make function! [generic_function [name of self] instruction21 ] ... func10: make function! [ instruction31 generic_function [name of self]] ---- If I don't have a "name of self" for function, each time I add a new function to call generic function, it is in the code of generic function that I would have to test the name of the function with a more or less gigantic number of test instructions: generic_function: make function ['function_name] [ if function_name = "func1" [ instruction11 instruction12 print function_name instruction13 ] if function_name = "func2" [ print function_name instruction21 ] ]

 [13/14] from: joel:neely:fedex at: 28-Mar-2002 8:14


Hi, Laplace, I guess I don't understand the problem you're trying to solve. laplace wrote:
> ... I want to do something like this ...: > generic_function: make function ['function_name]
<<quoted lines omitted: 15>>
> generic_function [name of self] > ]
First of all, let's remember that to REBOL the expression someword: func [] [print "Hi, Mom!"] first creates a FUNCTION! value, and then simply sets the (arbitrarily-named) word SOMEWORD to refer to that FUNCTION! value. It's a one-way arrow. It is just as meaningless to talk about "the name of a function" as it is to talk about "the color of a string" or "the mother of an integer". In the example you offer, GENERIC_FUNCTION is simply printing whatever value you supply as its argument. That being the case, you can pass it a string which contains a human-readable message, without worrying about which word was used to access the calling function. For example:
>> generic_function: func [s [string!]] [print s] >> func1: func [] [
[ ;do other stuff [ generic_function "Larry" [ ;do more other stuff [ ]
>> func2: func [] [
[ ;do other stuff [ generic_function "Curly" [ ;do more other stuff [ ]
>> func3: func [] [
[ ;do other stuff [ generic_function "Moe" [ ;do more other stuff [ ] Now you can get the behavior that you seem to want...
>> func1
Larry
>> func2
Curly
>> func3
Moe ... where invoking any of those functions causes the "generic" action to print a message. However, this approach lets you know *WHICH*FUNCTION* was invoked, regardess of how we got to that function value, as follows:
>> first-function: :func1 >> second-function: :func2 >> third-function: :func3
Now there are three additional words that refer to *THE*SAME* function values that we created earlier, but accessing them through these new references doesn't change the identity of each function.
>> first-function
Larry
>> second-function
Curly
>> third-function
Moe We can also create and use references to the functions without the need for words that refer to them individually.
>> block-o-funcs: reduce [:func1 :func2 :func3]
== [func [][ generic_function "Larry" ] func [][ generic_function "Curly" ] func [][ generic_functi... Now the same function values are in a block, which we can traverse to use the functions inside it.
>> foreach funcref block-o-funcs [funcref]
Larry Curly Moe We can store references to functions in other arbitrarily complicated structures:
>> look-up-table: []
== []
>> foo: tail block-o-funcs
== []
>> for char #"C" #"A" -1 [
[ foo: back foo [ append look-up-table reduce [char first foo] [ ] == [#"C" func [][ generic_function "Moe" ] #"B" func [][ generic_function "Curly" ] #"A" func [][ g... ... and then retrieve and evaluate the *SAME* functions.
>> for letter #"A" #"C" 1 [do select look-up-table letter]
Larry Curly Moe When we say "functions are first-class values in REBOL" we mean that they can be stored, retrieved, created, passed as arguments to functions, returned as values from functions,... in short, can be used as any other data type. This is A Good Thing, not a limitation, but it does require us to think about them a little differently than we do for more limited languages.
> If I don't have a "name of self" for function, each time I > add a new function to call generic function, it is in the
<<quoted lines omitted: 16>>
> ] > ]
This appears to be different from your original description, in that you're now embedding the behavior of what were the different functions into a single "master function" and letting its argument control which sub-expressions to evaluate. There are lots of ways to do something like this second example, as others have pointed out. You could also use refinements... generic_function: func [/type1 /type2 /type2 ...] [ if type1 [...] if type2 [...] if type3 [...] ... ] But this appears to be a step backwards. The Right Thing To Do is factor out the common, parameterizable behavior into its own identity, then use it with appropriate parameter(s) as needed. Hope this helps! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]

 [14/14] from: g:santilli:tiscalinet:it at: 28-Mar-2002 21:43


Hi Romano, On Wednesday, March 27, 2002, 3:13:08 PM, you wrote: RPT> 2) writing the func to be aware of itself (not of its name), with something RPT> like this: [...] ...and once you have 'SELF, you can look up if name (if it's a global) with: pick first system/words index? find second system/words self Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

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