Arc Forumnew | comments | leaders | submitlogin
1 point by rocketnia 4905 days ago | link | parent

"No, you don't give up # because Racket's reader already uses # for various stuff."

Just because the cost is paid once rather than once for each feature doesn't mean it isn't a cost. If we didn't use # for anything else, we could use it in symbols too. (Penknife allows # in symbols, for instance.)

If we take Racket as a starting point, then # is a heavily overloaded escape character and pretty hard to get rid of. How about changing it to \? :-p Then characters would be written not as #\a but as \\a --or maybe \c"a", if we insist not to use \ for anything but escaping.

---

"Why? We can already use mutable lists as hash table keys..."

Are you saying that makes sense? XD

Here's a http://tryarc.org/ session:

  arc> (= foo (tabl­e))
  #hash()
  arc> (= bar list.­2)
  (2)
  arc> (= foo.b­ar 'woo)­
  woo
  arc> foo
  #hash(((2 . nil) . woo))
  arc> (= bar.0­ 3)
  3
  arc> foo.bar
  nil
  arc> (each (k v) foo prn.v­)
  woo
  #hash(((3 . nil) . woo))
  arc> (each (k v) foo (prn foo.k­))
  nil
  #hash(((3 . nil) . woo))
  arc> (= (foo list.­2) 'boo)­
  boo
  arc> (= bar.0­ 2)
  2
  arc> (each (k v) foo prn.v­)
  boo
  woo
  #hash(((2 . nil) . woo) ((2 . nil) . boo))
  arc> keys.foo
  ((2) (2))
  arc> (each k keys.­foo (prn foo.k­))
  woo
  woo
  nil
This behavior seems to indicate that the table saves the hash of a key when it's entered and then doesn't update that hash when the key is mutated, and that it (probably) stores any keys with equal hashes so that they're checked for full equality in the order they were put in. However, the Racket docs just call the behavior "unpredictable" (http://docs.racket-lang.org/reference/hashtables.html), and that's just fine for a behavior that isn't here for any API-like reason, just here because it's an easier and more efficient implementation than more paranoid alternatives.

Anyway, I suspect you never meant mutable keys made that much sense, just that they make sense as long as we don't actually mutate them. :-p I'm fine with that, just like I'm fine with treating strings as immutable. (I guess one of the paranoid alternatives is to freeze anything used as a table key.)

---

That said, there's a completely different side to this topic I haven't gotten to: On Jarc, every table key is implicitly converted to a string for lookup purposes. I've brought up the point that it would be more consistent if Jarc simulated Racket 'equal? (which pg-Arc uses), but I don't really believe either of these things is the right thing to do, since they compare tagged values by their implementation content. So for my own purposes, I already consider it unpredictable what happens if I use non-symbol table keys, let alone mutable lists.



1 point by Pauan 4905 days ago | link

"Just because the cost is paid once rather than once for each feature doesn't mean it isn't a cost. If we didn't use # for anything else, we could use it in symbols too. (Penknife allows # in symbols, for instance.)"

I know, which is why I mentioned that we would probably need to write an Arc reader in order to unreserve | And if we did that, we would then also need to decide whether to use # or something else.

---

"If we take Racket as a starting point, then # is a heavily overloaded escape character and pretty hard to get rid of. How about changing it to \? :-p Then characters would be written not as #\a but as \\a --or maybe \c"a", if we insist not to use \ for anything but escaping."

Using \ as an escape does seem better than using # to be honest. If we were to write a reader in Arc (which I support, by the way), I think it'd be interesting to try out \ rather than #

---

"Are you saying that makes sense? XD"

I like it better than Python's "you can only store hashable things in keys" approach. Or JavaScript's insane "all keys are coerced to a string, so all Objects are put into the same key" approach.

---

"Anyway, I suspect you never meant mutable keys made that much sense, just that they make sense as long as we don't actually mutate them. :-p I'm fine with that, just like I'm fine with treating strings as immutable."

Yeah, something like that. I suspect Racket behaves that way for performance reasons, but ideally I think it'd be nice if it did update the hashes, so that mutable keys would behave as expected.

---

"(I guess one of the paranoid alternatives is to freeze anything used as a table key.)"

That's basically Python's approach: only hashable things are allowed as keys in objects.

-----

2 points by rocketnia 4904 days ago | link

"I know, which is why I mentioned[...]"

Yeah, I know. ^_^

---

"I like it better than Python's "you can only store hashable things in keys" approach."

Well... you can only use hashable things as keys in Racket too. (How else would hash tables work?) Almost everything in Racket is hashable, but it's possible to make things that kinda aren't, like this:

  arc> ($:define-­struct foo (dumm­y) #:pro­perty prop:­equal+hash­ (list­ (lamb­da args #t) (lamb­da args (erro­r "Can'­t prima­ry hash this.­")) (lamb­da args (erro­r "Can'­t secon­dary hash this.­"))))
  #<void>
  arc> (= my-ta­ble (tabl­e))
  #hash()
  arc> (= my-fo­o $.mak­e-foo!dumm­y-val)
  #<foo>
  arc> (= my-ta­ble.my-foo­ 2)
  Error: "Can't primary hash this."
This is using the 'equal? hash. I don't know if there's a way to make something in Racket that's unhashable with regard to 'eq? or 'eqv?.

You can get at these hash values directly using 'equal-hash-code and friends. http://docs.racket-lang.org/reference/hashtables.html

-----

1 point by Pauan 4904 days ago | link

"Well... you can only use hashable things as keys in Racket too."

Hm... odd, I remember in Python, that you weren't able to use things like lists (which are mutable) as keys... but I guess I remember wrong because I just tried it and it works. Not sure what the problem was that I had with Python's hash tables...

---

By the way, I feel like hash table keys should only use eq, not equal...

-----

1 point by rocketnia 4904 days ago | link

"By the way, I feel like hash table keys should only use eq, not equal..."

Racket has eq-based tables too those, and I wouldn't want 'equal? for weak table keys. However, if I want to use a list or something as a key, it's likely because I want to look something up using multiple values, in which case 'equal? is useful. (In those cases, the ability to intern something into an immutable data structure 'equal? to it would probably be just as useful....)

-----