Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive lambdas in F#

Take this example code (ignore it being horribly inefficient for the moment)

let listToString (lst:list<'a>) = ;;' prettify fix

    let rec inner (lst:list<'a>) buffer = ;;' prettify fix
        match List.length lst with 
        | 0 -> buffer
        | _ -> inner (List.tl  lst) (buffer + ((List.hd lst).ToString()))

    inner lst ""

This is a common pattern I keep coming across in F#, I need to have an inner function who recurses itself over some value - and I only need this function once, is there in any way possible to call a lambda from within it self (some magic keyword or something) ? I would like the code to look something like this:

let listToString2 (lst:list<'a>) = ;;' prettify fix

    ( fun 
        (lst:list<'a>) buffer -> match List.length lst with ;;' prettify fix
                                 | 0 -> buffer
                                 | _ -> ##RECURSE## (List.tl lst) (buffer + ((List.hd lst).ToString())) 
    ) lst "" 

But as you might expect there is no way to refer to the anonymous function within itself, which is needed where I put ##RECURSE##

like image 407
thr Avatar asked May 23 '09 19:05

thr


People also ask

Can a lambda function be recursive?

You may not realise that you can write AWS Lambda functions in a recursive manner to perform long-running tasks.

How do you recursively call lambda?

The recipe is simple: If you want to call a lambda recursively, just add an auto&& parameter taking the function again and call that. This produces basically optimal assembly and can be used in combination with capturing.

Can lambdas call themselves?

Bookmark this question. Show activity on this post. A regular function can contain a call to itself in its definition, no problem.

Can lambda function be recursive C++?

But a lambda cannot be recursive, it has no way to invoke itself.


1 Answers

Yes, it's possible using so called y-combinators (or fixed-point combinators). Ex:

let rec fix f x = f (fix f) x

let fact f = function
 | 0 -> 1
 | x -> x * f (x-1)


let _ = (fix fact) 5 (* evaluates to "120" *)

I don't know articles for F# but this haskell entry might also be helpful.

But: I wouldn't use them if there is any alternative - They're quite hard to understand.

Your code (omit the type annotations here) is a standard construct and much more expressive.

let listToString lst =

    let rec loop acc = function
        | []    -> acc
        | x::xs -> loop (acc ^ (string x)) xs

    loop "" lst
like image 110
Dario Avatar answered Sep 27 '22 22:09

Dario