Anonymous recursion

From Rosetta Code
Revision as of 20:48, 8 January 2011 by rosettacode>Kevin Reid (→‎{{header|JavaScript}}: Note that arguments.callee will not be available in ES5 Strict mode.)
Task
Anonymous recursion
You are encouraged to solve this task according to the task description, using any language you may know.

While implementing a recursive function, it often happens that we must resort to a separate "helper function" to handle the actual recursion.

This is usually the case when directly calling the current function would waste too many resources (stack space, execution time), cause unwanted side-effects, and/or the function doesn't have the right arguments and/and return values.

So we end up inventing some silly name like "foo2" or "foo_helper". I have always found it painful to come up with a proper name, and see a quite some disadvantages:

  • You have to think up a name, which then pollutes the namespace
  • A function is created which is called from nowhere else
  • The program flow in the source code is interrupted

Some languages allow you to embed recursion directly in-place. This might work via a label, a local gosub instruction, or some special keyword.

Anonymous recursion can also be accomplished using the Y combinator.

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.


Ada

This example is incorrect. Please fix the code and remove this message.

Details: Just making a function invisible is not anonymous recursion. See the talk page for an explanation.

In Ada you can define functions local to other functions/procedures. This makes it invisible to outside and prevents namespace pollution.

Better would be to use type Natural instead of Integer, which lets Ada do the magic of checking the valid range. <lang Ada> function Fib (X: in Integer) return Integer is

     function Actual_Fib (N: in Integer) return Integer is
     begin
        if N < 2 then
           return N;
        else
           return Actual_Fib (N-1) + Actual_Fib (N-2);
        end if;
     end Actual_Fib;
  begin
     if X < 0 then
        raise Constraint_Error;
     else
        return Actual_Fib (X);
     end if;
  end Fib;</lang>

AutoHotkey

If: <lang ahk>fib(n) { if(n < 0)

               return error
       else if(n < 2)
               return 1
       else
               return n * fib(n-1)

}</lang> Ternary: <lang ahk>fib(n) { return n < 0 ? "error" : n < 2 ? 1 : n * fib(n-1) }</lang>

Clojure

This example is incorrect. Please fix the code and remove this message.

Details: Just a minor error: The test (< n 0) should be before the 'loop'.

The JVM as of now has no Tail call optimization so the default way of looping in Clojure uses anonymous recursion so not to be confusing. <lang clojure> (defn fib [n]

   (loop [n n, v1 1, v2 1] 

(cond (< n 0) (throw (new IllegalArgumentException "n should be > 0")) (< n 2) v2 true (recur (- n 1) v2 (+ v1 v2))))) </lang>

Forth

This example is incorrect. Please fix the code and remove this message.

Details: Defining an anonymous function is not anonymous recursion. Also,the check for a negative argument is not outside the recursion. See the talk page for an explanation.

Recursion is always anonymous in Forth, allowing it to be used in anonymous functions. <lang forth>defer fib

noname ( n -- fib )
 dup 2 < if 0 max exit then
 1- dup recurse swap 1- recurse + ;  is fib
test ( n -- ) 0 do i fib . loop ;

11 test</lang>

J

Copied directly from the fibonacci sequence task, which in turn copied from one of several implementations in an essay on the J Wiki: <lang j> fibN=: (-&2 +&$: -&1)^:(1&<) M."0</lang>

Note that this is an identity function for arguments less than 1 (and 1 (and 5)).

Examples: <lang j> fibN 12 144

  fibN  i.31

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040</lang>

(This implementation is doubly recursive except that results are cached across function calls.)

$: is an anonymous reference to the largest containing verb in the sentence.

JavaScript

<lang javascript>function fibo(n) {

 if (n < 0)
   throw "Argument cannot be negative";
 else
   return (function(x) {
     if (n < 2)
       return 1;
     else
       return arguments.callee(n-1) + arguments.callee(n-2);
   })(n);

}</lang>

Note that arguments.callee will not be available in ES5 Strict mode.

Mathematica

An anonymous reference to a function from within itself is named #0, arguments to that function are named #1,#2..#n, n being the position of the argument. The first argument may also be referenced as a # without a following number, the list of all arguments is referenced with ##. Anonymous functions are also known as pure functions in Mathematica.

<lang Mathematica> check := #<0& fib := If[check[#],Throw["Negative Argument"],If[#<=1,1,#0[#-2]+#0[#-1]]&[#]]& fib /@ Range[0,10]

{1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89} </lang>

Making sure that the check is only performed once.

<lang Mathematica> check := (Print[#];#<0)& fib /@ Range[0,4] 0 1 2 3 4

{1, 1, 2, 3, 5} </lang>

PicoLisp

<lang PicoLisp>(de fibo (N)

  (if (lt0 N)
     (quit "Illegal argument" N) )
  (recur (N)
     (if (> 2 N)
        1
        (+ (recurse (dec N)) (recurse (- N 2))) ) ) )</lang>

Explanation: The above uses the 'recur' / 'recurse' function pair, which is defined as a standard language extensions as <lang PicoLisp>(de recur recurse

  (run (cdr recurse)) )</lang>

Note how 'recur' dynamically defines the function 'recurse' at runtime, by binding the rest of the expression (i.e. the body of the 'recur' statement) to the symbol 'recurse'.

Python

<lang python>>>> Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args))) >>> fib = lambda f: lambda n: None if n < 0 else (0 if n == 0 else (1 if n == 1 else f(n-1) + f(n-2))) >>> [ Y(fib)(i) for i in range(-2, 10) ] [None, None, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</lang>

Ruby

Works with: Ruby version 1.9

This fib() method uses a recursive block. We must provide the block with a reference to itself. The simplest way is to use a local variable 'f' of the fib() method. The block is a closure that can access 'f'.

<lang ruby>def fib(n)

 raise ArgumentError, "fib of negative" if n < 0
 (f = proc { |n| n < 2 && n || f[n - 1] + f[n - 2] })[n]

end</lang>

<lang ruby>(-2..12).map { |i| fib i rescue :error } => [:error, :error, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]</lang>

To remove the local variable 'f' from the fib() method, we can use a second block to limit the scope of 'f', or change 'f' to a block parameter.

<lang ruby># Limit the scope of 'f' to a block.

  1. Kernel#catch calls the block and returns the value of the block.

def fib(n)

 raise ArgumentError, "fib of negative" if n < 0
 catch { (f = proc { |n| n < 2 && n || f[n - 1] + f[n - 2] })[n] }
 # f is undefined here

end

  1. Change 'f' to a block parameter.
  2. Notice that f.tap { |f| r } => f
  3. but f.tap { |f| break r } => r

def fib(n)

 raise ArgumentError, "fib of negative" if n < 0
 proc { |f, n| n < 2 && n || f[f, n - 1] + f[f, n - 2] }
   .tap { |f| break f[f, n] }
 # f is undefined here

end</lang>


Works with: Ruby version 1.8

The problem with Ruby 1.8 is that a block cannot have its own variables. The previous code would only clobber the single varible 'n' of the fib() method. The fix is to define a recursive method. One can define a singleton method on a new object. This works with both Ruby 1.8 and Ruby 1.9.

<lang ruby>def fib(n)

 raise ArgumentError, "fib of negative" if n < 0
 o = Object.new  # This singleton method is not polluting
 def o.call(n)   # the namespace of any other objects.
   n < 2 && n || call(n - 1) + call(n - 2)
 end
 o.call n

end </lang>

Tcl

This solution uses Tcl 8.5's lambda terms, extracting the current term from the call stack using introspection (storing it in a local variable only for convenience, with that not in any way being the name of the lambda term; just what it is stored in, and only as a convenience that keeps the code shorter). The lambda terms are applied with the apply command. <lang tcl>proc fib n {

   # sanity checks
   if {[incr n 0] < 0} {error "argument may not be negative"}
   apply {x {

if {$x < 2} {return $x} # Extract the lambda term from the stack introspector for brevity set f [lindex [info level 0] 1] expr {[apply $f [incr x -1]] + [apply $f [incr x -1]]}

   }} $n

}</lang> Demonstrating: <lang tcl>puts [fib 12]</lang> Prints

144

UNIX Shell

This example is incorrect. Please fix the code and remove this message.

Details: Just making a function invisible is not anonymous recursion. See the talk page for an explanation.

The shell does not have anonymous functions. Every function must have a name. However, one can create a subshell such that some function, which has a name in the subshell, is effectively anonymous to the parent shell.

<lang bash>fib() {

 if test 0 -gt "$1"; then
   echo "fib: fib of negative" 1>&2
   return 1
 else
   (
     fib() {
       if test 2 -gt "$1"; then
         echo "$1"
       else
         echo $(( $(fib $(($1 - 1)) ) + $(fib $(($1 - 2)) ) ))
       fi
     }
     fib "$1"
   )
 fi

}</lang>

<lang bash>$ for i in -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12; do > fib $i > done fib: fib of negative fib: fib of negative 0 1 1 2 3 5 8 13 21 34 55 89 144</lang>

Ursala

<lang Ursala>#import nat

fib =

~&izZB?( # test the sign bit of the argument

  <'fib of negative'>!%,   # throw an exception if it's negative
  {0,1}^?<a(               # test the argument to a recursively defined function
     ~&a,                  # if the argument was a member of {0,1}, return it
     sum^|W(               # otherwise return the sum of two recursive calls
        ~&,                # to the function thus defined
        predecessor^~(     # with the respective predecessors of
           ~&,             # the given argument
           predecessor)))) # and the predecessor thereof</lang>

Anonymous recursion is often achieved using the recursive conditional operator, ( _ )^?( _ , _ ), which takes a predicate on the left and a pair of functions on the right, typically one for the base and one for the inductive case in a recursive definition. The form ^?< can be used if the relevant predicate is given by membership of the argument in a constant set, in which case only the set needs to be specified rather than the whole predicate.

The recursive conditional operator ^? differs from the ordinary conditional ? seen at the outermost level by arranging for its predicate and component functions to be given an input of the form where is the original argument, and is a copy of the whole function. Code within the function body may then access itself anonymously according to all the usual language idioms pertaining to deconstruction of tuples, and call itself by any of several recursion combinators, such as the pairwise recursion form W seen above.