4 ms·
I don't really understand your objection. How is >at least a differently scoped variable of the same name referring to the same value, but that's not lexical s
by ImprobableTruth 5y ago
I don't really understand your objection. How is
>at least a differently scoped variable of the same name referring to the same value, but that's not lexical scoping anymore
not lexical scoping? That's literally just how closures work under the hood.
And that's exactly why closures have to deal with references (or copies) - every implementation of them is a function pointer and a record for the lexical environment, the latter of which requires that at closure creation time the relevant bindings are captured, either by creating a reference or making a copy.
I also don't understand why C++'s (or Rust's) closures would be 'fake'. If you capture by reference, they work exactly like the closures of other languages. Not having a GC just means you have to be wary of lifetimes. If you use a reference counting pointer (/some other GC'd pointer) you literally have the same closures as other languages.
- jhgb 5y ago> How is ... not lexical scoping? That's literally just how closures work under the hood. In the presence of references in the language, these two cases may be observationally indistinguishable (maybe, I'm not a C++ guru?) but they're still different language features. Lexical scoping does not require taking a reference. > And that's exactly why closures have to deal with references (or copies) No, they don't. They deal with bindings. References are either an explicit thing you create (as in, int &b=a; or such), or a parameter passing mechanism...but a free variable is neither (it's not a parameter to the closure in any case), and it exists even in languages with no notion of references whatsoever, such as for example Scheme. > I also don't understand why C++'s (or Rust's) closures would be 'fake'. If you capture by reference, they work exactly like the closures of other languages. Not having a GC just means you have to be wary of lifetimes. Yeah, and that's at least one of the things that make it fake. Why would you have to be wary about lifetimes? Closures in languages that support them Just Work(TM).
- CornCobs 5y agoWhat do you mean by "languages with no notion of references whatever"? At least in Scheme I think references are a pretty immediately obvious feature. It's not like every assignment does a deep copy, nor does free variable capture in closures. The moment you do stuff with set-car! and friends you are very explicitly working with references
- jhgb 5y agoScheme doesn't have references. > The moment you do stuff with set-car! and friends you are very explicitly working with references No, you're not. At least not in the sense that references are references in C++ or in the established CS term call-by-reference. Likewise, you probably wouldn't say that C has references because you can "do stuff" with pair->car=foo; in C.
- hackinghaskell 5y agoYes, you are. Notwithstanding the fact that C pointers are syntactically not really references, at least in my opinion, the way to spell an example for what they are referring to in C would be "pair = foo". You aren't modifying *pair, but the reference object stored in your own private stack frame. As long as mutability is out of the picture and the aptly named notion of referential transparency is preserved, there is no way to discern whether any two symbols reference the same value. The moment you flip the proverbial page to chapter 3 of SICP and start using setter-functions!, you lose this. You should very much become aware of the fact you are working with references whenever you mutate things, because the mental model of lists as values falls apart when you write, for example: (define a (list 1 2 3)) (define b (cdr a)) (set-car! b 'ta-da!) (display a) And then get left to perplexedly stare at the REPL's output. It is true that references are not, in some sense, a language-level/opt-in feature of Scheme, as in that you cannot arbitrarily create a reference to an integer, but cons cells very much are represented by references to them only, in much the same way as class types in Java are.
- ImprobableTruth 5y ago>References are either an explicit thing you create (as in, int &b=a; or such), or a parameter passing mechanism This strikes me as an unusual definition. I'd say that references are simply a pointer that is treated like the underlying value i.e. they're 'boxed' values. This is a notion that is essentially present in all languages. e.g. Java (or Scheme) which don't have some explicit reference feature, still have 'unboxed' values (e.g. integers) and 'boxed' values (e.g. lists). >They deal with bindings. Sure, to create a closure, you need to capture the relevant bindings (the lexical environment). But how does on deal with bindings? Well, a binding associates a variable to a value. Now, when you capture a binding, you can either point to the original binding (capture by reference) or copy the value (capture by value). >Why would you have to be wary about lifetimes? I mean, that's just how these languages are, right? Even if you do something incredibly mundane, like returning a value or calling a function with a parameter, you constantly have to be aware of lifetimes. That's why to me it seems like a completely orthogonal issue to closures.