Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Hissp – A Lisp-Flavored Python (hissp.readthedocs.io)
4 points by gilch on Jan 18, 2021 | hide | past | favorite | 2 comments


How is this different from Hy?

https://docs.hylang.org/en/stable/


From the Hissp FAQ: https://hissp.readthedocs.io/en/v0.2.0/faq.html#i-got-here-f...

They’re both Lisps that can import Python, but Hissp has a very different approach and philosophy.

I was also a major contributor to the open-source Hy project. Hy is obviously a much older project than Hissp with more contributors and more time to develop. While my experience with Hy informs my design of Hissp, Hissp is not a fork of Hy’s source code, but a completely new project with a fundamentally different architecture.

The biggest difference is that Hy compiles to Python abstract syntax trees (or “AST”, an intermediate stage in the compilation of Python code to Python bytecode). In contrast, Lissp works more like ClojureScript: the Lissp language uses Hissp as its AST stage instead, and compiles that to Python code, which Python then compiles normally. Hy compiles to a moving target—Python’s AST API is not stable. This helps to make Hissp’s compiler simpler than Hy’s.

Hy has an intermediate layer of Hy model objects it uses to represent code, although it tries to convert them automatically, this can make it even more confusing. E.g. (type '42) is <class 'hy.models.HyInteger'> in Hy, but <class 'int'> in Lissp.

Except for tuples, which represent invocations, and strings, which represent raw Python (and module literals/qualifiers), Hissp’s representation for Python objects are simply the objects. Hissp will at least attempt to compile in anything, even if it has no literal representation in Python code, by falling back to pickle, if necessary. Hy will just crash if you insert anything it can’t model.

This means that Hissp has a much higher degree of homoiconicity than Hy.

Hissp code is made of ordinary Python tuples that serve the same role as linked lists in other Lisps, or Hy’s model objects. Using these directly in Python (“readerless mode”) is much more natural than writing code using Hy’s model objects, although using the Lissp (or Hebigo) language reader makes writing these tuples even easier than doing it directly in Python.

Hissp is designed to be more modular than Hy. It supports two different readers (Lissp and Hebigo) with the potential for more. These compile different languages that represent the same underlying Hissp trees. The separate Hebigo language is indentation-based, like Python, while the included Lissp reader uses the traditional S-expressions.

Hy code requires the hy package as a dependency. You need Hy’s import hooks just to load Hy code. But Hissp only requires hissp to compile the code to Python. Once that’s done, the output has no dependencies other than Python itself. (Unless you import some other package, of course.) This may make Hissp more suitable for integration into other projects where Hy would not be a good fit due to its overhead.

Hy’s compiler has a special form for every Python statement and operator and has to do a lot of work to create the illusion that its statement special forms behave like expressions. This complicates the compiler a great deal, and doesn’t even work right in some cases, but allows Hy to retain a very Python-like feel. The unparsed AST also looks like pretty readable Python. Not quite what a human would write, but a good starting point if you wanted to translate a Hy project back to Python.

But after writing Drython, I realized that the expression subset of Python is sufficient for a compilation target. There is no need to do the extra work to make statements act like expressions if you only compile to expressions to begin with. It turns out that Hissp only required two special forms: quote and lambda. (And you could almost implement lambda via a text macro.) This makes Hissp’s compiler much simpler than Hy’s, and makes full code-walking macros much easier to implement, because once all the macros are expanded, there aren’t that many special cases to deal with. But, the lack of statements makes it feel a bit more like Scheme and a bit less like Python. And, of course, the expression-only output, while a direct and sensible translation once you understand Hissp, is completely unpythonic.

Another major difference is Hissp’s module literals and qualified symbols, which allows macros to easily import their requirements from other modules. Macro dependencies are much harder to work with in Hy. Lissp’s template quote automatically qualifies symbols like Clojure does. Hy can’t do that.

Hy passes Python keyword arguments using HyKeywords, while Lissp passes them using symbols, so print(1, 2, 3, sep=",", end="!\n") in Python would be (print 1 2 3 :sep "," :end "!\n") in Hy and (print 1 2 3 : sep "," end #"!\n") in Lissp.

Hissp’s lambda special form parallels this call syntax for defining parameters, with : as the separator; :? as a placeholder; :* and :** to parallel unpacking; plus :/ for positional-only, based on Python’s syntax. Hy’s syntax on the other hand, has to use special symbols &optional, &rest, &kwonly, and &kwargs, based on Common Lisp’s approach to distinguish its parameter types, in addition to the #* and #** it uses for unpacking. It can’t do positional-only parameters at all yet.




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

Search: