25 ms·
Hy is a great project. One unfortunate thing, though, is that no one has been able to successfully implement `let`, which makes writing idiomatic lisp almost im
by alschwalm 9y ago
Hy is a great project. One unfortunate thing, though, is that no one has been able to successfully implement `let`, which makes writing idiomatic lisp almost impossible. I'm curious if anyone can actually prove it can't be done or is just very difficult (or too slow to be useful).
- rcarmo 9y agoThis. See my other comment for a sizable Hy example and more info, but the lack of "let" mostly killed it for me.
- nnq 9y ago> but the lack of "let" mostly killed it for me Can you give an example of code that is improved by let significantly? ...and can't be rewritten in a more readable way without it?
- hk__2 9y ago> Can you give an example of code that is improved by let significantly Any piece of code that uses a variable.
- nnq 9y agoI'd be more inclined to day that let mostly encourages you to write zillion-line functions (instead of lots of small ones), simply because with it you "mentally can" since you can see the scope of variables better. But.. do you really prefer to write huge functions instead of smaller ones? Also: I think Python's default args being evaluated at function definition time kills the need for the usage of let when defining closures inside loops (you can just pas the value you want to capture in a closure as the default value of a param) or other things like that.
- hk__2 9y ago> I'd be more inclined to [s]ay that let mostly encourages you to write zillion-line functions (instead of lots of small ones), simply because with it you "mentally can" since you can see the scope of variables better. That’s true. I revise my comment as "Any piece of code that uses a variable[ to hold something you use multiple times and don’t want to recompute]."; for example creating an API client then using it twice.
- aidenn0 9y agoAny macros that expands to code that will reuse a value. You can't do common, and valuable, constructs like once-only without let.
- nnq 9y agoHmm. Can't argue against this. I agree, this is a legitimate case. Probably I'm a bit too stuck on "the python way" on this clash-of-cultures to see such cases that are clearly part of "the lisp way"...
- such_a_casual 9y ago(defun udpate () (let ((pos (find-char-pos))) (move-char pos)) (print (stats)) (rotate enemies)) (defun udpate () (set 'pos (find-char-pos)) (move-char pos) (print (stats)) (rotate enemies)) I now have to keep this 'pos symbol in my head for the rest of the function (in another language, forever in this case), whereas in the first example I can just forget about the variable after the next line. It doesn't exist anymore. It makes code clearer and much easier to refactor since I can immediately see everywhere that the variable is used.
- nnq 9y agoI get it, despite having a small issue with "forever" being defined as "just 2 more loc", but I just: (1) feel more drawn to "Flat is better than nested." from "Zen of Python" to dislike the extra scoping level despite the conceptual clarity it provides (because I'm sure some "idiot" will abuse it and I'll end up reading a 10 nested let-s monstrosity pretty soon) (2) like to write small functions, so forever will always be "~10 loc max" for me ...so imho if you're used to "thinking in classic Lisps" you'll miss let, otherwise you won't. What I'd miss for example would be some Haskell-like where (https://wiki.haskell.org/Let_vs._Where#Advantages_of_where https://wiki.haskell.org/Let_vs._Where#Advantages_of_where) but I'd wake quickly out of it since it would make no sense to someone not already "stuck in Haskell-like thinking mode".
- jazzdev 9y ago(defun udpate () (ag-if (find-char-pos) (move-char it)) (print (stats)) (rotate enemies)) Doesn't Hy's anaphoric macros solve this? And one could even argue it's more readable.
- such_a_casual 9y agoI don't know what that is (tried googling it), but it doesn't look like it's doing the same thing as let.
- deleted 9y ago[deleted]
- deleted 9y ago[deleted]
- flavio81 9y ago> Can you give an example of code that is improved by let significantly? "Let" is one of the most important special operators in Lisp. It allows you to create lexical variables within an s-expression. Roughly equivalent to creating local variables within a block (in other languages). So i'd claim it is essential.
- nerdponx 9y agoWhat is it about `let` that makes it so hard to implement?
- alschwalm 9y agoThere is a description of the problem here: https://github.com/hylang/hy/issues/1056 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.
- thaumasiotes 9y agoI'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.
- Tenobrus 9y agoI think the problem is, then constructs such as yield (the behavior of which depends on the current function scope), would no longer work correctly.
- nerdponx 9y agoCouldn't `let` be a compile-time expansion using `gensym` or some other symbol mangling? Or is that what the contrib macro does?
- tuturto 9y agoI actually wrote a short blog post about this just recently: https://engineersjourney.wordpress.com/2017/08/01/history-of-let/ 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.
- shuzchen 9y agoHy actually used to have a let (but a broken one) and it was removed in a recent version. For context on this see https://github.com/hylang/hy/issues/1056 https://github.com/hylang/hy/issues/1056
- aidenn0 9y agoIs there something about Hy's lambda that makes implementing let with it not possible? For those unaware, the transformation is roughly: (let ((foo bar) ...) Y) -> ((lambda (foo ...) Y) bar ...) [edit] Reading around it seems that it breaks several pythonic control-transfer functions that treat functions specially (e.g. yield from inside a let would be surprising). Without knowing much about Hy's semantics, it should still be doable by rewriting variable names. That's likely not doable in a robust manner via a macro though, so would have to be part of Hy's transformation from sexpr to ASTs.