Returning functions from functions: TRADFNS vs DFNS
7 posts
• Page 1 of 1
Returning functions from functions: TRADFNS vs DFNS
Tradfns allow you to return functions, but dfns don't. What's the history and reasoning for this distinction?
Apologies if this is discussed somewhere on the Forum or in the documentation. This can be quite a useful feature! [P.S. This is a contrived, simple example. Its usefulness is in more complex cases.]
See also the APL Wiki: https://aplwiki.com/wiki/Defined_function_(traditional)
- Code: Select all
⎕FX 'R←TESTT N' ':IF N=1 ⋄ R←+ ⋄ :ELSE ⋄ R←- ⋄ :ENDIF'
2 (TESTT 1)3
5
2 (TESTT 0)3
¯1
TESTD←{ ⍵=1: + ⋄ -} ⍝ Or try _←+ etc..
2 (TESTD 1)3
SYNTAX ERROR
TESTD[0] TESTD←{⍵=1:+ ⋄ -}
∧
Apologies if this is discussed somewhere on the Forum or in the documentation. This can be quite a useful feature! [P.S. This is a contrived, simple example. Its usefulness is in more complex cases.]
See also the APL Wiki: https://aplwiki.com/wiki/Defined_function_(traditional)
- petermsiegel
- Posts: 143
- Joined: Thu Nov 11, 2010 11:04 pm
Re: Returning functions from functions: TRADFNS vs DFNS
If you could get your hands on John Scholes' wonderful presentation at Dyalog'11 (https://en.wikipedia.org/wiki/John_M._S ... les2011-66) you would probably find a lot of answers. Unfortunately, it does not seem to be on YouTube. I was there at the Dyalog User Group Meeting in 2011 and I remember bits of it. At the time John also distributed an experimental version of the interpreter in which dfns could return functions in addition to arrays. So, if you could get your hands on the presentation I am sure you would find it very interesting. How to go about it, though, I don't know...
-
StefanoLanzavecchia - Posts: 109
- Joined: Fri Oct 03, 2008 9:37 am
Re: Returning functions from functions: TRADFNS vs DFNS
Thanks for sharing that. I remember that interpreter. I'm not sure, but that one (or another one?) had closures (bundling persistent state with returned functions) as well, which were/are very useful.
thanks again.
thanks again.
- petermsiegel
- Posts: 143
- Joined: Thu Nov 11, 2010 11:04 pm
Re: Returning functions from functions: TRADFNS vs DFNS
There's this clumsy way how to simulate function setting:
It's better than nothing.
-Veli-Matti
SetSort←{Sort∘←⍋ ⋄ 1=⍵:⍵ ⋄ Sort∘←⍒ ⋄ ⍵}
It's better than nothing.
-Veli-Matti
- Veli-Matti
- Posts: 93
- Joined: Sat Nov 28, 2009 3:12 pm
Re: Returning functions from functions: TRADFNS vs DFNS
Thank you for the suggestions.
The workaround I selected was to enclose the workhorse dfn inside a tradfn that (given the right option) returns a dfn as a result. It works fine, but it is a kludge nonetheless.
The workaround I selected was to enclose the workhorse dfn inside a tradfn that (given the right option) returns a dfn as a result. It works fine, but it is a kludge nonetheless.
- petermsiegel
- Posts: 143
- Joined: Thu Nov 11, 2010 11:04 pm
Re: Returning functions from functions: TRADFNS vs DFNS
While dfns don't come with closures out of the box, you can easily make them yourself:
No need to defer the choice of which function to return to the tradfn; we can let the workhorse dfn return an Object Representation and only let the container tradfn return it bound as operand to an operator which will apply the function at call time, since Object Representations become functions when used as operands:
closure←⎕NS⍬Since a scalar cannot be sorted, we use the scalar argument to set state:
closure.asc←1
Sort←closure.{⍬≡⍴⍵:asc⊢←⍵ ⋄ asc:⍋⍵ ⋄ ⍒⍵}
⎕EX'closure'
'hello'[Sort 'hello']We created the namespace separately and have remove it afterwards. At the cost of readability, we can inline its definition:
ehllo
Sort 0
'hello'[Sort 'hello']
ollhe
Sort 1
'hello'[Sort 'hello']
ehllo
Sort←({⍵⊣⍵.asc←1}⎕NS⍬).{⍬≡⍴⍵:asc⊢←⍵ ⋄ asc:⍋⍵ ⋄ ⍒⍵}Once we get array notation, this becomes much neater:
Sort←(asc:1).{⍬≡⍴⍵:asc⊢←⍵ ⋄ asc:⍋⍵ ⋄ ⍒⍵}But right, dfns are not allowed to return functions (or operators). The ability of tradfns to do so was probably never planned, but just fell out of the implementations, and while not a documented feature, it isn't going away. It can therefore be used to preserve the source of tacit functions which would otherwise be lost or mangled immediately at definition time:
∇ F←AvgHowever, this doesn't work for the closure, as it'd re-create the namespace upon every invocation. Instead, we can define a tradfn which replaces itself with, and returns, the actual function. This function can safely be stored in a text source file:
F←+⌿÷1⌈≢
∇
∇ F←Sort
⎕EX'Sort'
F←Sort←({⍵⊣⍵.dir←1}⎕NS ⍬).{⍬≡⍴⍵:dir⊢←⍵ ⋄ dir:⍋⍵ ⋄ ⍒⍵}
∇
petermsiegel wrote:enclose the workhorse dfn inside a tradfn that (given the right option) returns a dfn as a result.
No need to defer the choice of which function to return to the tradfn; we can let the workhorse dfn return an Object Representation and only let the container tradfn return it bound as operand to an operator which will apply the function at call time, since Object Representations become functions when used as operands:
∇ F←TEST N;or
or←{f←+ ⋄ g←- ⋄ ⍵:⎕OR'f' ⋄ ⎕OR'g'}N
F←or{2=⎕NC'⍺':⍺ ⍺⍺ ⍵ ⋄ ⍺⍺ ⍵}
∇
-
Adam|Dyalog - Posts: 135
- Joined: Thu Jun 25, 2015 1:13 pm
Re: Returning functions from functions: TRADFNS vs DFNS
Very clever (and workable) solution, especially the Object Representation snippet. Thank you.
- petermsiegel
- Posts: 143
- Joined: Thu Nov 11, 2010 11:04 pm
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group