logoalt Hacker News

ahartmetzlast Wednesday at 10:01 AM3 repliesview on HN

I guess closures in languages like Scheme can have multiple "methods"? In C++ and Rust, closures (lambdas) are one function with attached state variables. I guess there are ways to attach more callables to a bag of state, but they would involve one lambda for each callable and shared state captured by reference (and good luck dealing with lifecycle issues).


Replies

antonvslast Wednesday at 6:29 PM

> I guess closures in languages like Scheme can have multiple "methods"?

At the language implementation level, Scheme-like closures only have one operation, which is the ability to apply them to arguments and thus evaluate them. But as a couple of the other replies show, a closure's code can be implemented as a dispatcher which handles multiple methods. That's not a language feature, just user code.

I wrote the koan quoted above in 2003, a few years before Graydon Hoare started working on Rust. At the time, there weren't any "static" languages with built-in support for closures.

Even Python had only had read-only closure support for a couple of years at that point - so those closures couldn't be used to implement mutation of closed-over variables. (Python didn't get mutable closures until around 2008.) Java only got closure support in version 8 around 2014. C++ 11 got closures in 2011.

Of course you can implement dynamic-dispatching objects using closures in Rust or C++, but that's not going to be the equivalent of a statically-defined structure.

gpderettalast Wednesday at 10:36 AM

a tuple of closures closing over the same object ('let over lambda') is equivalent to an interface.

llmslave2last Wednesday at 10:30 AM

You can do it multiple ways. Like in go:

   cloj := func() {
     val := 1
     return func(m string) {
       switch m {
         case "inc": val = val + 1
         case "dec": val = val - 1
       }
     }
   } ()
   
   cloj("inc")

In JS you can close upon state and return an object, which is essentially how classes work in the language.

   let cloj = (() => {
     let x = 0; return { inc: () => x++, dec: () => x-- }
   })()
   cloj.inc()