3 ms·
closures are a poor man's objects…
by bfung 3y ago
closures are a poor man's objects…
- solomonb 3y ago"At that moment, Anton became enlightened."
- bfung 3y ago:)
- adrian_b 3y agoI am not at all convinced that it is useful to have closures in a programming language. The implementation of closures is completely unnecessary for any of the features that exist in functional languages or in any programming languages. The avoidance of closures becomes possible when the programming language includes the restriction that inside a function body the only external variables (i.e. which are neither parameters nor local variables) that are visible are those that are allocated statically, either as process-local or as thread-local. This restriction is similar with the restrictions from C or from traditional C++, but it is less constraining, because nested functions are allowed, they just cannot see the stack-allocated variables from enclosing blocks, unless they are passed as parameters. Any useful thing that can be implemented with stack-allocated variables captured inside a closure can also be done with statically-allocated variables, but in a much more efficient way and in a way that is less prone to subtle bugs. Other applications of closures in LISPy languages are just workarounds for the impossibility of defining record or structure types. In any language with user-defined data types such closure applications are not needed. The only significant difference between a language with closures and one without closures, from the programmer POV, is that in a language without closures for each variable that is accessed inside a function body without being passed as a parameter, the programmer must add an allocation-class specifier, such as "static" or "thread_local". This is a good thing in my opinion, because sometimes bugs are caused by unintentionally accessing external variables, which are automatically captured in closures. A "purely" functional program must not access inside function bodies any variables that are not passed as parameters. Avoiding to write explicit "static" annotations, in order to make closures masquerade as functions, does not change the fact that such functions are no longer pure functions, but automata, which is good, whenever this is necessary. When there are no closures, any function pointer can be just a simple pointer and any higher-order functions can have a faster implementation, which is better for any functional language. Closures add a completely unnecessary overhead.
- solomonb 3y agoFYI the message you are responding to is a reference to this ancient copypasta: ``` The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures." Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress. On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened. ```
- tsimionescu 3y agoNote that Java fits your definition (though it allows one extra type of variable to be accessed, members of the current instance). It is probably the only popular language that supports local functions but not closures. Also, C++ doesn't suffer from the problem of accidentally capturing variables, since it requires you to explicitly state which variables from the external env you want to reference (with the [a, b] syntax at the start of a lambda declaration; a lambda starting with [] fits your desired constraints).
- adrian_b 3y agoThanks for pointing to Java. I have not thought about it, because I use Java only very seldom. The members of the current instance are not really an extra type of variable. They are the members of one hidden function parameter. While they are distinguished in the source code, in the translated machine code there is no difference between them and the explicit function parameters. I agree that this is a good feature of C++, that it avoids the bugs caused by accidental captures by giving control to the programmer on what may be captured. Nevertheless, perhaps it would have been possible to have a simpler implementation of the C++ lambda-declared functions than with the current function objects, by simply disallowing the capture of stack-allocated local variables.
- mrkeen 3y agoIf closures are a poor man's objects, then lambdas are a poor man's anonymous inner classes.
- bfung 3y agoobjects are a poor man’s closures…