M2 icon indicating copy to clipboard operation
M2 copied to clipboard

Bug related to symbols and HashTables

Open grunkgrunk opened this issue 3 years ago • 2 comments

Hey there!

I have encountered this weird thing with HashTables, which might be a bug. I'm running the latest version (1.19.1) but this is also true for 1.18. Lets define some functions:

expected1 = () -> ( 
    hashTable {foo => 2}
)

expected2 = () -> ( 
    hashTable {symbol foo => 2}
)

weird = () -> (
    foo := "now foo has a name";
    hashTable {symbol foo => 2}
)

The first two functions work as expected. For example (expected1())#foo returns 2. However (weird())#foo gives me this error: stdio:899:11:(3): error: key not found in hash table. I have found a workaround:

workaround = () -> ( foo := "now foo has a name"; value toString hashTable {symbol foo => 2} )

Now (workaround())#foo gives me 2.

grunkgrunk avatar Dec 10 '21 12:12 grunkgrunk

This is how symbols work. It can be a bit confusing but, here's a basic description of how they work.

  1. Symbols are a name + dictionary, the name (or SymbolBody) is a name, and the dictionary tell us in what scope the symbol was declared
  2. If a name is not used/declared, a new global symbol with that name is created
  3. If a name is declared and you call symbol foo, it gives you the symbol corresponding to that variable
  4. foo := "something" creates a new local symbol with a name of foo (and gives the corresponding variable a value of "something")
  5. This default can be overridden by using local foo or global foo instead of symbol foo

So in your case, (weird())#foo gives an error because the foo inside of weird is local to the function weird, but the foo you are indexing by is global, and so these count as different symbols because the come from different dictionaries. There's some more details that I didn't discuss here, but this gives you the right intuition most of the time.

Your workaround works because value doesn't use the local scope, and so it doesn't see the foo variable in that scope. You could also use global foo instead. Or use the "." operator which treats the second argument as a global symbol.

jkyang92 avatar Dec 10 '21 15:12 jkyang92

Ahh I see, that makes sense. Thanks for giving such a thorough explanation!

grunkgrunk avatar Dec 10 '21 16:12 grunkgrunk