Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What is it about `let` that makes it so hard to implement?


There is a description of the problem here: https://github.com/hylang/hy/issues/1056

I think it really comes down to python having limited scoping capabilities (I think you can only really make new scopes with function declarations), this can maybe be hacked around, but at too high a performance cost to be usable.


I actually wrote a short blog post about this just recently: https://engineersjourney.wordpress.com/2017/08/01/history-of...

In short, let kept running into trouble with yield, exceptions, breaking out of loops and such. It would have been really tricky (probably close to impossible) to get everything working correctly.


In case i ever find myself designing a programming language, what facilities would Python have to support in order to allow 'let' to work? It seems to me that in theory Hy could solve the problem with which variables are to be marked 'nonlocal' by doing a lot of additional code analysis (is this correct?).

I gather that the main remaining problem is that break, continue, yield, async, await work differently if you covertly introduce a new function scope. Would it be sufficient if scopes could have explicit labels and break, continue, yield took an argument that said which label to break/continue/yield out of? Would that solve the problem with async, await too?

If Hy did extensive code analysis to determine where to introduce 'nonlocal', and if Python's break/continue/yield took this extra argument, would implementation of 'let' by Hy then become possible or are there still additional impediments that i am missing?


(tuturto responded to the parent of this comment at https://engineersjourney.wordpress.com/2017/08/01/history-of... )


I'm curious too. Conceptually, `let` defines a function of n variables and then invokes it on a list of n values:

    (let ((a 3)
          (b 5)
          (c -1))
      (* a (+ b c)))

    def «gensym»(a,b,c):
        return (a * (b + c))
    «the-gensym»(3,5,-1)
It seems workable purely in terms of the code transformation. But, I haven't tried.


I think the problem is, then constructs such as yield (the behavior of which depends on the current function scope), would no longer work correctly.


Couldn't `let` be a compile-time expansion using `gensym` or some other symbol mangling? Or is that what the contrib macro does?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: