I’m going through Joel Martin’s amazing teaching tool, mal, which teaches you how to write your own Lisp from scratch. I wanted to get a little better at Javascript, and so chose to use it as my language of implementation.

I’m really glad I’m writing Javascript in the realm of ES6, but there was a bit of hoisting that definitely took me by surprise.


function EVAL(ast, env) {
  ...
  switch (ast[0]) {
    case "def!":
      [__, first, second] = ast
      let value = EVAL(second, env)
      ...
      return value
    case "let*":
      [__, first, second] = ast
      ...
      return EVAL(second, newEnv)
    ...

...

It turns out that even with the array destructuring, the variable is hoisted into the global context. I only detected this issue with a def that was nested in a let. In those situations, the variable ‘second’ would be overidden in the nested call, so that it would actually change when it returned to the caller.

If only I had remembered to enable strict mode