@shirleyquirk: About the YCombinator

> trying to get closer to whatever the hell haskell does...

Everything is lazy in Haskell, so to do the same thing in a strict language 
like Nim, we need to inject some laziness with differed execution using thunks.

As per [my RosettaCode Y-Combinator in Nim 
contribution](https://rosettacode.org/wiki/Y_combinator#Nim), the usual 
name-calling implementation of the true YCombinator with injected laziness:
    
    
    import sugar
    
    proc ycombo[T](f: () -> T -> T): T = # can't be `func` because Nim thinks 
`g` is global...
      type RecursiveFunc = object # any entity that wraps the recursion!
        recfnc: (RecursiveFunc -> T)
      let g = (x: RecursiveFunc) => f(() => x.recfnc(x))
      g(RecursiveFunc(recfnc: g))
    
    
    Run

However, as noted in the Haskell contribution, Nim has direct function 
name-recursion as does Haskell, so this can be more directly implemented as:
    
    
    import sugar
    
    func ycombo[T](f: () -> T -> T): T = f(() => ycombo(f))
    
    
    Run

Note that the above is not the direct value-recursion that can be written in 
Nim but disallowed by the RosettaCode Task; in Haskell, the distinction is 
often made that value-recursion shares the value, whereas name-recursion 
doesn't:
    
    
    import sugar
    
    func ycombo[T](f: () -> T -> T): T =
      var x: T; x = f(() => x); x
    
    
    Run

All three versions can be used for the try Y-Combinator factorial and Fibonacci 
functions as shown in RosettaCode.

Reply via email to