3 ms·
> And you can do the same in Lisp, but, like Python and other languages, it doesn't happen for you. No, the state of a Lisp or Python object isn't a value. You
by catnaroek 10y ago
> And you can do the same in Lisp, but, like Python and other languages, it doesn't happen for you.
No, the state of a Lisp or Python object isn't a value. You can't pass it around without manually deep-cloning everything. Cloning a value doesn't even make sense - there's always only one of it!
> The only reason Haskell doesn't have the same is that it's pure, at least in theory, so there isn't a meaningful distinction.
ML isn't pure, but it confines physical equality to mutable objects, and not everything is a mutable object. This discussion has absolutely nothing to do with purity.
> But in languages where state is mutatable, you need eq, or an equivalent, for when you have to care about object identity.
Haskell and ML have lots of mutable state, and don't need a distinction between eq and equal. The single equality testing operator does the right thing on values of different types.
- qwertyuiop924 10y ago>Haskell and ML have lots of mutable state, and don't need a distinction between eq and equal. The single equality testing operator does the right thing on values of different types. No, it doesn't. If you truly have a single equality operator, no pointer casting (like C or Rust have to solve this problem), and mutability, than you can't have object identity as needed. And I think Haskell actually does have generic pointer types, so you can effectively do pointer casting, so it does, in effect, have eq. >No, the state of a Lisp or Python object isn't a value. You can't pass it around without manually deep-cloning everything. Cloning a value doesn't even make sense - there's always only one of it! Values are purely abstract. We can compare them, create them, mutate them, etc., but they're all objects under the surface. It doesn't make sense to treat objects as values consistantly, except in functional languages. Everywhere else, it's expensive, impractical, and annoying (sometimes you want eq without jumping through hoops to get it). You seem to think that this has nothing to do with mutability, but if you're data's mut, your proposed semantics require deep copy on funcall by default, which is unacceptable. So it has everything to do with mutability.
- catnaroek 10y ago> No, it doesn't. If you truly have a single equality operator, no pointer casting (like C or Rust have to solve this problem), and mutability, than you can't have object identity as needed. In Haskell and ML, object identities are first-class values just like everything else, and using the single equality operator on them has exactly the same effect as using eq in Lisp. > And I think Haskell actually does have generic pointer types, so you can effectively do pointer casting, so it does, in effect, have eq. Given a reference cell, you can check its contents. But, given a value, you can't get the abstract location where it resides. And this is a good thing! > Values are purely abstract. Values are as concrete as it gets in my day-to-day programming. Just like numbers and characters are concrete in Lisp, only with many more values than those. > We can compare them, create them, mutate them, etc., but they're all objects under the surface [emphasis mine]. In a computer's memory, yes. But the semantics of a programming language isn't a computer's memory. Inability to see past possible implementations is the distinguishing trait of the abstraction-challenged! > Everywhere else, it's expensive, impractical, and annoying (sometimes you want eq without jumping through hoops to get it). Using reference cells doesn't seem like “jumping through hoops” to me. More like “explicitly stating my intent”. The language conveniently distinguishes the cell from its contents, even when I forget to do so myself. > You seem to think that this has nothing to do with mutability, but if you're data's mut, your proposed semantics require deep copy [emphasis mine] on funcall by default, which is unacceptable. So it has everything to do with mutability. Not necessarily. Another alternative is requiring values to be used at most once. Which is exactly what Rust does with things that don't support shallow copying. --- To see why equality is completely broken in Lisp, consider the following situation: You have two “lists” of “lists” (in the Lisp sense), and you want to compare the outer “lists” by value (`equal`), but the inner “lists” by object identity (`eq`). What would you do? (0) In Standard ML, I'd just use the type `foo list ref list`, where `foo` is the element type of the inner lists. Then the equality operator `op=` automagically does the right thing. (1) In Haskell, it's exactly the same thing as in ML, only with different syntax: `[IORef [Foo]]` and `(==)`. (2) I don't know what the most convenient solution would be in Lisp, but I was told in #lisp at Freenode that the idiomatic way involves using a `loop` plus some tricky thing to abort the outer “list” comparison as soon as you find a pair of non-`eq` inner “lists”. Whoa.
- 10y ago