convex
convex copied to clipboard
Consider strictly throwing error when compiling code referring to undefined synbols
We could make it an error to do something like:
(defn f [x] (undeclared-symbol x))
This would add some additional safety at the cost of some extra code and transaction costs to declare symbols in advance, e.g. the following would then work:
(declare undeclared-symbol)
(defn f [x] (undeclared-symbol x))
A nice consequence of doing this would be that dynamic lookups can probably be optimised since they can infer the precise account they need to read from. This is actually possibly a performance win (examining environments dynamically isn't particularly cheap....)
I was thinking about roughly a year ago but didn't come up with a satisfying solution up to this day.
While pretty much all languages forbid referencing undeclared symbols, I find it not so trivial in the context of smart contracts. Say we know undeclare the undeclared-symbol that was carefully declared when f was defined. What happens to f?
Nothing would immediately break but f would throw :UNDECLARED if it tried to look up the value. I think that is reasonable behaviour. You might even want this if e.g. you were updating a smart contract in stages.
That's kind of what happens in Clojure: undeclaring a symbol makes it point to an instance of Unbound so that computation fails since it cannot be coerced to anything useful.
So yes, reasonable but then declaring should be seen as an optimization only: counter-intuitively, it does not guarantee that a symbol is declared at any point in time. Maybe there is a better, less confusing terminology. allocate?
I'd rather keep declare as a name for consistency both with Clojure and the general programming concept of making a forward declaration.
Though it's a bit asymmetric with undef..... I suppose the way to thing about it is that declare is like a partial def without a value. undef will remove either.