Anonymous recursion: Difference between revisions

Content added Content deleted
Line 439: Line 439:
=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==


The following solution works in both languages. A cache is used
The following solution works in both languages. A cache is used to improve performance.

to improve performance.
The use of co-expressions for this purpose was probably never intended by the designers and is more than a bit intensive and definitely NOT recommended. Just because we CAN do something, doesn't mean we should do it. And in this case is on par with trying to kill an ant with an A-bomb.
<lang unicon>procedure main(A)

This example does accomplish the goals of hiding the procedure inside ''fib'' so that the type and value checking is outside the recursion. It also does not require an identifier to reference the inner procedure; but, it requires a local variable to remember our return point. Also, each recursion will result in the current co-expression being refreshed, essentially copied, placing a heavy demand on co-expression resources.

<lang Icon>procedure main(A)
every write("fib(",a := numeric(!A),")=",fib(a))
every write("fib(",a := numeric(!A),")=",fib(a))
end
end
Line 455: Line 459:
if type(n) == "integer" & n >= 0 then
if type(n) == "integer" & n >= 0 then
return n @ makeProc {{
return n @ makeProc {{
i := @(source := &source)
i := @(source := &source) # 1
/cache[i] := ((i-1)@makeProc(^&current)+(i-2)@makeProc(^&current))
/cache[i] := ((i-1)@makeProc(^&current)+(i-2)@makeProc(^&current)) # 2
cache[i] @ source
cache[i] @ source # 3
}}
}}
end
end
Line 465: Line 469:
return (@A, A) # prime and return
return (@A, A) # prime and return
end</lang>
end</lang>

Some of the code requires some explaining:
* The double curly brace syntax after ''makeProc'' serves two different purposes, the outer set is used in the call to create a co-expression. The inner one binds all the expressions together as a single unit.
* At #1 we remember where we came from and receive ''n'' from our caller
* At #2 we transmit the new parameters to refreshed copies of the current co-expression setup to act as a normal procedure and cache the result.
* At #3 we transmit the result back to our caller.
* The procedure ''makeProc'' consumes the the first transmission to the co-expression which is ignored. Essentially this primes the co-expression to behave like a regular procedure.



For reference, here is the non-cached version:
For reference, here is the non-cached version:
<lang unicon>procedure fib(n)
<lang Icon>procedure fib(n)
local source, i
local source, i
if type(n) == "integer" & n >= 0 then
if type(n) == "integer" & n >= 0 then
Line 476: Line 488:
}}
}}
end</lang>
end</lang>
The performance of this second version is 'truly impressive'. And I mean that in a really bad way. By way of example, using default memory settings on a current laptop, a simple recursive non-cached fib out distanced the non-cached fib above by a factor of 20,000. And a simple recursive cached version out distanced the cached version above by a factor of 2,000.


=={{header|J}}==
=={{header|J}}==