I'm currently re-writing it in Python 3.6 because Hy has taken a hard stance in backwards compatibility and deprecated "let" (with a replacement macro, but still) and isn't tackling async (both for understandable, but sad reasons), so it doesn't really work for me anymore.
But while it did, I loved it to bits. Python with a LISP syntax is just wonderful, and if someone ever finds a way to add back the stuff I like, I'm more than willing to deal with the quirks.
I know python, and last semester I took a class that briefly touched (lightly kissed?) LISP for a few weeks. I have a passing familiarity and I really loved the very small amount that I saw. I'd like to learn more, can you go into more detail on the usage of let and how one would go without it?
and to directly answer your question, there a are many things you can do with let. Let binds a "form" to a symbol.
(let ((pi 3.14))
... code goes here ... )
So within the "code" part, that is, within that lexical environment, the symbol "pi" exists and is bound to float number 3.14
(Alternatively, you don't need to set a initial value.)
One of the interesting uses of let is that it can also redefine dynamic variables (aka special variables, think of them as "global variables).
So for example let's assume i define timeout to 300, so within my whole package, this special variable has the value of 300. Let's suppose this variable is going to be read by function "my-function", and others.
So i create this special variable:
(defparameter *timeout* 300)
Now, despite the above, let's suppose i want to call "my-function" but with a timeout of 1000. I can just do this in my code:
(let ((*timeout* 1000))
(my-function))
So, inside this "let", when "my-function" gets executed, the timeout will be 1000. Outside of this, it will still be 300.
Let, thus, allows you easy use of lexical environments.
Another use is creating closures by using the combination of "let" with "lambda."
> I'd like to learn more, can you go into more detail on the usage of let and how one would go without it?
Welcome to the wonderful world of Lisp.
I'd recommend to you to install Portacle (the Portable Common Lisp Environment), this allows you to code in Lisp straight away.
As for tutorials, "Practical Common Lisp" (free online book) is fun, modern, and excellent for introducing you to most CL concepts, including of course use of let, let*, etc.
Thank you for sharing this. The last time I started trying to use Hy, I felt like I was basically writing Python but wrapped in parens -- I felt like I was doing something wrong, but couldn't place what it was, so it's nice to see a non-toy implementation that demonstrates what one can do with it.
My main use cases: Doing data analysis using Numpy, Pandas, sklearn. Calling AWS API using Boto. Calling GDAX API using their Python code samples.
I also use it for small personal scripts.
My first choice for one-off scripts would have been Clojure. But the long startup time for Clojure apps makes it unusable for quick command line scripts. Hy gives us the best of both worlds.
There are a few projects on my github (elfsternberg) that I've used Hy for.
One thing that I've also done is write the first draft in Hy, and then used Hy2Py to generate the version that I'm going to publish. This does result in a lot of compiling-by-hand, but the end product is often surprisingly robust.
On the other hand, it's also very (!) un-pythonic. Hy discourages classes in favor of closures, like Scheme, so I end up with a lot of nested sub-functions. My project git-linter looks like that. Hy encourages highly functional thinking, and git-linter is just that: the inputs are things like the configuration file, available linters, the command line, and (depending on the command) either the output of a "git-status --porcelain" or just "find . -type f"; the output is a report on the various outputs of the linters. It's a very straightforward map/reduce/filter, so no object-orientated code at all was required.
To an engrained Pythonista who must make a class for every last step, this land-of-verbs approach tends to look strange.
I'm not sure I'd call the class explosions that a lot of people are writing these days Pythonic. Lots of older Python code was written with functions and a very occasional class. I think the last decade has seen an upward trend the usage of classes in Python due to the influence of Java and how software engineering is taught in colleges.