ML Closure vs Scheme Closure

IIUC in ML lexical binding of variables leads to a copy of the variable, whereas in Scheme it is a binding to the variable memory location itself. Is there a common terminology to differentiate between the two different kinds of bindings? Am I understanding the difference correctly?

It also seems to me that the ML approach has a positive effect from a software engineering approach because it doesn't lead to a strong implicit coupling between modules. Has that idea been explored in the literature?

I am thinking of using ML style closures in my next language, what is the modern thinking on such an approach?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The same thing

They're the same thing semantically. In both cases lexical closures capture the binding - the translation between a symbol and it's "meaning" in a context. It's just that in Scheme variables are bound to mutable cells whereas in ML variables are bound to immutable cell. If you want mutation in ML, you bind the variable to a ref - the cell is still immutable, but the ref is mutable (even when captured).

For a third data point, Scala lies somewhere in between. It has both mutable and immutable cells and either can be captured by a closure. It doesn't have first class ML style refs, but you can certainly build one if you need it.

Operationally there might be a difference in capturing immutable vs immutable cells. With immutable cells, Scala will copy references or small "primitives" but with mutable cells Scala silently creates an extra level of indirection when the compiler sees that the cell can be captured.

If your language has mutability and you want to make copies on capture, one question to ask is "how deep should the copy be?" If parts of a structure are mutable then the choice will be visible to the program.

In terms of implementation...

Some (many? most?) scheme compilers assume all variables are immutable. To preserve proper semantics, these implementations automatically insert refs around any variable that might get mutated.

So yes, not only are they essentially the same on a semantic level, the difference in implementation is sometimes not so big either.

Previously on LtU

There was another related discussion awhile ago.

Thanks James

Thanks a lot James. I appreciate the clarification and link.

Also on LtU

This article is also directly relevant.