Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Every object in OOP is potentially stateful, some are made stateless and immutable but most are not, you need to read the docs. If I build a composite object Z from objects X and Y, the set of possible states Z has is a product of the set of possible states X and Y have. No complicated theory, just basic mathematics. I spent many years building OOP systems before moving on to FP. I strongly disagree with the claim that it is easy to manage state in OOP!


State doesn't magically disappear in FP. It just isn't given a name but it's still here, in your closures.


Functional programming languages do not capture mutable state in closures.


> Functional programming languages do not capture mutable state in closures.

Yes, they can. In ML, you can build a function that returns a set of closures that manipulate or use shared mutable state. I'm quite sure you can do something equivalent in Haskell, too.

As always, “it depends” whether you would actually want to do that.


The reference type in ML/OCaml is an opt-in feature, a container with it's own special type. In Haskell, you can also capture IORefs or similar, but any reads/writes to them are effectful and captured in the types. The point is that Python does this all the time as the default. Any captured variable could potentially change under your feet. It is rarely useful and most beginners do not expect it, hence it is commonly considered a "gotcha".


So LISP and Caml aren't functional programming language nowadays ? Because both allow you to modify what's in a closure.


Apparently we went through some magic event that only Haskell is entitled to be the one and only functional programming language.


There is no language definition or implementation called "LISP". Both Scheme and OCaml lexically capture variables by value, as if they have been passed in as arguments. This is not how it works in e.g. Python.


Python has had closures exactly the same as Scheme and OCaml since the year 2000.

What it lacks is a multiline anonymous function syntax.

See PEP 227: https://www.python.org/dev/peps/pep-0227/


No they are not exactly the same.

From the link you posted: "all uses of the name within the block are treated as references to the current block"

The Python folks call them "late binding closures" and they are frequently discussed as "gotchas".

Essentially lexically scoped variables are captured as references to mutable state. Java did not make this mistake, perhaps because they had Guy Steele (of Scheme fame) on the committee. It is a questionable default that ultimately just destroys ones ability to reason about programs.


> It is a questionable default that ultimately just destroys ones ability to reason about programs.

If that destroys one's ability to reason about programs, then one never really had the ability to reason about one's programs in the first place.

It's not like nested block scopes are some boon to program comprehensibility anyway.


Wait, isn't that exactly how lexical scoping in Scheme works?

That's how you implement "objects" using lambdas. You make closures that mutate their closed-over bindings.


The question is if you mutate the variable, create a closure, mutate the variable, create a closure, and so on -- do those closures -- when executed -- each use the value that the variable had at the time the individual closure was created, or do they all use the latest value that the variable had? Scheme (and other academic languages) do the first, Python (and other scripting languages) do the second.

But the problem with program comprehensibility comes from doing these gymnastics with block scope and anonymous functions in the first place. The right thing to do is to give things proper names and interfaces.

In other words, both what Scheme does and what Python does are bad for reasoning about programs, precisely because the semantics of what should be done in this scenario are implicit and unable to be discerned solely by reading the code. Since either behavior is non-obvious, and understanding the program relies on this implicit behavior, the practice of mutating a variable while repeatedly creating closures over it should be avoided.


No, multiple closures in Scheme will not capture different values of the same, mutated variable. For that to happen, the block has to be re-entered such that a fresh binding is created for those variables. That is not mutation.

Scheme's version of the do loop actually performs fresh binding, rather than mutation, so lambdas in the do loop capture the iterations separately.

If you mutate a variable with set!, all the closures over that variable see the change.


Thanks, "mutate" was definitely the wrong word in my post. The trouble here is that Python doesn't have syntax to do a binding rather than an assignment.


There is an ANSI standard for Common Lisp, though. And ML and OCaml have a “reference” type that was built for the explicit purpose of having mutable contents.


The ML/OCaml reference type is an opt-in feature with its own type and explicit syntax, it is not the default used pervasively everywhere. That's the key difference that makes ML programs easier to reason about.


> There is no language definition or implementation called "LISP".

Well, yes there actually is: the Lisp 1 language that MacCarthy and friends developed on the IBM 704, and its immediate follow-ups through Lisp 1.5. Since that, there isn't.


There is a basic rule: all languages carrying Lisp in their name implement much of the core of McCarthy's Lisp:

Emacs Lisp, ISLISP (which is defined by an ISO standard) Standard Lisp, Common Lisp (which has an ANSI Standard), ...

Languages in the wider Lisp family, which are more or less incompatible (Logo, Clojure, Dylan, ...) don't use Lisp in their name.


yes, there is; Common Lisp and it is an Ansi standard. This is what is commonly understood as "Lisp" (noun) as opposed as when writing "a Lisp" (adjective), in which case it could be Scheme, Racket, Clojure, etc.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: