Anonymous recursion: Difference between revisions

m
imported>Arakov
(22 intermediate revisions by 14 users not shown)
Line 18:
;Task:
If possible, demonstrate this by writing the recursive version of the fibonacci function   (see [[Fibonacci sequence]])   which checks for a negative argument before doing the actual recursion.
;Related tasks:
:*   [[Y combinator]]
 
<br><br>
 
Line 380 ⟶ 383:
f()(x,1,1)</syntaxhighlight>
 
=={{header|BASIC}}==
 
==={{header|BaCon}}===
<syntaxhighlight lang="freebasic">
 
Line 423 ⟶ 426:
</syntaxhighlight>
 
==={{header|BASIC256}}===
 
=={{header|BASIC256}}==
{{trans|AutoIt}}
<syntaxhighlight lang="basic256">print Fibonacci(20)
Line 450 ⟶ 452:
55</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
<syntaxhighlight lang="qbasic">100 cls
110 sub fib(num)
120 if num < 0 then print "Invalid argument: "; : fib = num
130 if num < 2 then fib = num else fib = fib(num-1)+fib(num-2)
140 end sub
190 print fib(20)
200 print fib(30)
210 print fib(-10)
220 print fib(10)
230 end</syntaxhighlight>
{{out}}
<pre>Same as BASIC256 entry.</pre>
 
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
This works by finding a pointer to the 'anonymous' function and calling it indirectly:
Line 464 ⟶ 480:
55
</pre>
 
==={{header|IS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "Fibonacc.bas"
110 FOR I=0 TO 10
120 PRINT FIB(I);
130 NEXT
140 DEF FIB(K)
150 SELECT CASE K
160 CASE IS<0
170 PRINT "Negative parameter to Fibonacci.":STOP
180 CASE 0,1
190 LET FIB=K
200 CASE ELSE
210 LET FIB=FIB(K-1)+FIB(K-2)
220 END SELECT
230 END DEF </syntaxhighlight>
 
=={{header|Bracmat}}==
Line 1,017 ⟶ 1,049:
 
=={{header|Elena}}==
ELENA 46.x:
<syntaxhighlight lang="elena">import extensions;
 
fib(n)
{
if (n < 0)
{ InvalidArgumentException.raise() };
^ (n) {
if (n {> 1)
{ if (n > 1)
^ this self(n {- 2) + (this self(n - 1))
}
^ this self(n - 2) + (this self(n - 1))
}else
{ else
^ {n
^ n }
}(n)
}(n)
}
 
public program()
{
for (int i := -1,; i <= 10,; i += 1)
{
console.print("fib(",i,")=");
try
{
console.printLine(fib(i))
}
catch(Exception e)
{
console.printLine:("invalid")
}
};
console.readChar()
}</syntaxhighlight>
{{out}}
Line 1,091 ⟶ 1,122:
{{out}}
102334155
 
=={{header|EMal}}==
<syntaxhighlight lang="emal">
fun fibonacci = int by int n
if n < 0 do
logLine("Invalid argument: " + n) # logs on standard error
return -1 ^| it should be better to raise an error,
| but the task is about recursive functions
|^
end
fun actualFibonacci = int by int n
return when(n < 2, n, actualFibonacci(n - 1) + actualFibonacci(n - 2))
end
return actualFibonacci(n)
end
writeLine("F(0) = " + fibonacci(0))
writeLine("F(20) = " + fibonacci(20))
writeLine("F(-10) = " + fibonacci(-10))
writeLine("F(30) = " + fibonacci(30))
writeLine("F(10) = " + fibonacci(10))
</syntaxhighlight>
{{out}}
<pre>
F(0) = 0
F(20) = 6765
Invalid argument: -10
F(-10) = -1
F(30) = 832040
F(10) = 55
</pre>
 
=={{header|Erlang}}==
Line 1,324 ⟶ 1,385:
=={{header|Fōrmulæ}}==
 
{{FormulaeEntry|page=https://formulae.org/?script=examples/Anonymous_recursion}}
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation &mdash;i.e. XML, JSON&mdash; they are intended for storage and transfer purposes more than visualization and edition.
 
'''Solution.'''
Programs in Fōrmulæ are created/edited online in its [https://formulae.org website], However they run on execution servers. By default remote servers are used, but they are limited in memory and processing power, since they are intended for demonstration and casual use. A local server can be downloaded and installed, it has no limitations (it runs in your own computer). Because of that, example programs can be fully visualized and edited, but some of them will not run if they require a moderate or heavy computation/memory resources, and no local server is being used.
 
It consists in having a local function inside the main function, so it is neither visible nor available outside. The local function is defined after the validation, so if the input is invalid, neither the definition nor its invocation is performed.
In '''[https://formulae.org/?example=Anonymous_recursion this]''' page you can see the program(s) related to this task and their results.
 
[[File:Fōrmulæ - Anonymous recursion 01.png]]
 
'''Test cases'''
 
[[File:Fōrmulæ - Anonymous recursion 02.png]]
 
[[File:Fōrmulæ - Anonymous recursion 03.png]]
 
=={{header|Go}}==
===Y combinator===
Y combinator solution. Go has no special support for anonymous recursion.
<syntaxhighlight lang="go">package main
Line 1,388 ⟶ 1,458:
fib 40 = 102334155
fib undefined for negative numbers
</pre>
 
===Closure===
<syntaxhighlight lang="go">
package main
 
import (
"errors"
"fmt"
)
 
func fib(n int) (result int, err error) {
var fib func(int) int // Must be declared first so it can be called in the closure
fib = func(n int) int {
if n < 2 {
return n
}
return fib(n-1) + fib(n-2)
}
 
if n < 0 {
err = errors.New("negative n is forbidden")
return
}
 
result = fib(n)
return
}
 
func main() {
for i := -1; i <= 10; i++ {
if result, err := fib(i); err != nil {
fmt.Printf("fib(%d) returned error: %s\n", i, err)
} else {
fmt.Printf("fib(%d) = %d\n", i, result)
}
}
}
</syntaxhighlight>
{{out}}
<pre>
fib(-1) returned error: negative n is forbidden
fib(0) = 0
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
</pre>
 
Line 1,528 ⟶ 1,651:
fib2(x floor)
)</syntaxhighlight>
 
=={{header|IS-BASIC}}==
<syntaxhighlight lang="is-basic">100 PROGRAM "Fibonacc.bas"
110 FOR I=0 TO 10
120 PRINT FIB(I);
130 NEXT
140 DEF FIB(K)
150 SELECT CASE K
160 CASE IS<0
170 PRINT "Negative parameter to Fibonacci.":STOP
180 CASE 0
190 LET FIB=0
200 CASE 1
210 LET FIB=1
220 CASE ELSE
230 LET FIB=FIB(K-1)+FIB(K-2)
240 END SELECT
250 END DEF</syntaxhighlight>
 
=={{header|J}}==
Line 1,664 ⟶ 1,769:
 
=={{header|K}}==
{{works with|Kona}}
<syntaxhighlight lang="k">fib: {:[x<0; "Error Negative Number"; {:[x<2;x;_f[x-2]+_f[x-1]]}x]}</syntaxhighlight>
{{works with|ngn/k}}:
<syntaxhighlight lang=K>fib: {:[x<0; "Error Negative Number"; {:[x<2;x;o[x-2]+o[x-1]]}x]}</syntaxhighlight>
'''Examples:'''
<syntaxhighlight lang="k"> fib'!10
Line 1,702 ⟶ 1,810:
=={{header|Kotlin}}==
{{trans|Dylan}}
<syntaxhighlight lang="scalakotlin">fun fib(n: Int): Int {
require(n >= 0)
fun fib1fib(k: Int, a: Int, b: Int): Int =
if (k == 0) a else fib1fib(k - 1, b, a + b)
return fib1fib(n, 0, 1)
}
 
Line 1,752 ⟶ 1,860:
8}
-> 34
</syntaxhighlight>
 
=={{header|Lang}}==
<syntaxhighlight lang="lang">
fp.fib = ($n) -> {
if($n < 0) {
throw fn.withErrorMessage($LANG_ERROR_INVALID_ARGUMENTS, n must be >= 0)
}
fp.innerFib = ($n) -> {
if($n < 2) {
return $n
}
return parser.op(fp.innerFib($n - 1) + fp.innerFib($n - 2))
}
return fp.innerFib($n)
}
</syntaxhighlight>
 
Line 2,257 ⟶ 2,384:
{{trans|PicoLisp}}
<code>recur</code> isn't built into Perl, but it's easy to implement.
<syntaxhighlight lang="perl">sub recur :prototype(&@) {
my $f = shift;
local *recurse = $f;
Line 2,839 ⟶ 2,966:
144
</pre>
 
=={{header|RPL}}==
===Hidden variable===
The recursive part of the function is stored in a local variable, which is made accessible to all the recursive instances by starting its name with the <code>←</code> character.
{{works with|HP|48G}}
≪ ≪ '''IF''' DUP 1 > '''THEN'''
DUP 1 - ←fib EVAL
SWAP 2 - ←fib EVAL +
'''END''' ≫ → ←fib
≪ '''IF''' DUP 0 <
'''THEN''' DROP "Negative value" DOERR
'''ELSE''' ←fib EVAL '''END'''
≫ ≫ '<span style="color:blue">FIBAR</span>' STO
 
-2 <span style="color:blue">FIBAR</span>
10 <span style="color:blue">FIBAR</span>
{{out}}
<pre>
1: 55
</pre>
===Truly anonymous===
Both the recursive block and the argument are pushed onto the stack, without any naming. This meets the requirements of the task perfectly and works on any RPL machine, but it is far from idiomatic and uses a lot of stack space.
{{works with|HP|28}}
≪ '''IF''' DUP 0 <
'''THEN''' DROP "Negative value"
'''ELSE'''
≪ '''IF''' DUP 1 > '''THEN'''
DUP2 1 - OVER EVAL
ROT ROT 2 - OVER EVAL +
'''ELSE''' SWAP DROP '''END'''
SWAP OVER EVAL
'''END'''
≫ '<span style="color:blue">FIBAR</span>' STO
 
=={{header|Ruby}}==
Line 3,456 ⟶ 3,617:
 
=={{header|Wren}}==
<syntaxhighlight lang="ecmascriptwren">class Fibonacci {
static compute(n) {
var fib
Anonymous user