HN Gopher Feed (2017-08-02) - page 1 of 10 ___________________________________________________________________
Hy
433 points by tosh
https://hy.readthedocs.io/en/stable/___________________________________________________________________
alschwalm - 4 hours 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).
aidenn0 - 52 minutes ago
Is 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.
rcarmo - 4 hours ago
This. See my other comment for a sizable Hy example and more
info, but the lack of "let" mostly killed it for me.
nnq - 2 hours ago
> but the lack of "let" mostly killed it for meCan 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 - 2 hours ago
> Can you give an example of code that is improved by let
significantlyAny piece of code that uses a variable.
nnq - 2 hours ago
I'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 - 1 hours 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.
nerdponx - 4 hours ago
What is it about `let` that makes it so hard to implement?
thaumasiotes - 4 hours ago
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.
Tenobrus - 3 hours ago
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.
nerdponx - 1 hours ago
Couldn't `let` be a compile-time expansion using `gensym`
or some other symbol mangling? Or is that what the contrib
macro does?
alschwalm - 4 hours ago
There is a description of the problem here:
https://github.com/hylang/hy/issues/1056I 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.
shuzchen - 4 hours ago
Hy 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
evanwolf - 2 hours ago
Next on the wishlist: an APL inside Python.
IgorPartola - 2 hours ago
As a heavy user of Python, and someone who grew up with the "curly
braces" languages, I have a question for y'all. Is this really
readable? (setv result (- (/ (+ 1 3 88) 2) 8)) Or rather is it
more readable than result = ((1 + 3 + 88) / 2) - 8 I just... Do
you just get used to this, or is it something that you have to keep
struggling with? Especially given that the latter is how we do math
the rest of the time?
dustingetz - 1 hours ago
In clojure you write it like this, so the parens indicate scope.
No need to mutate an environment here. dunno about hy (let
[result (- (/ (+ 1 3 88) 2) 8)] ; result defined inside the
expression only )
erikpukinskis - 19 minutes ago
I would never use a variable name like result, it's meaningless.
And the inner values should be labeled too, with their own
variable names. Any compiler worth its salt will optimize the
names away.
cannonpr - 55 minutes ago
I used to be mostly a Python guy, fell in love with Clojures
syntax, you get used to it surprisingly fast, and it's caused me
less headaches than 'interesting' pythonic syntax. That having
been said, I still love Python too.
kazinator - 13 minutes ago
There are advantages:Long Lisp expressions break into multiple
indented lines according to a couple of very easy rules: (- (/
(+ 1 3 ;; basically a tree (-) --- (/) --- (+) -- 1 3
8 8) ;; | | `- 8 8
2) ;; | ` 2 8)
;; `- 8 by contrast, there is any
satisfactory, canonical way to break up infix into multiple
lines. Thus, Lisp expressions can be longer while remaining
understandable. (Which is important because entire function
definitions, for instance, are really one big expression.)There
is no ambiguity in Lisp expressions. The parentheses are not
optional grouping punctuators, but operators denoting operator
application (analogous to the parentheses in f(x, y)). You never,
ever have to grapple with "what is the precedence/associativity
of this?" or "I know the precedence/associativity of this, but
did the person who wrote this intend it that way?"Sufficiently
long expressions are hard to read in any notation. Just like in
any language, Lisp programs break down complex calculations with
intermediate variables: (let ((bytes (+ 1 3 8 8)) ;; what is
this term? Oh, bytes (words (/ bytes 2)) ;; why divide
it by two? Ah 16 bit words (size (- words 8))) ;; Why
subtract? Account for some header or whatever. ...)
deathanatos - 1 hours ago
This is the main reason Lisp has just never grown on me. I'm
certain ? and other responses demonstrate ? that the readability
can certainly be improved here. Yes, a programming language needs
nothing more than parens. But dedicating a tastefully chosen set
of sigils seems to make a lot of difference, in my opinion.
kbp - 1 hours ago
I understand this point of view if most of your programs are
just doing arithmetic, but once you start using functions and
procedures the differences are pretty minimal.
evilduck - 2 hours ago
It's just training. Buy and use a RPN calculator and lisp
suddenly seems normal.(To answer your question directly, yes it's
readable. You learn to look past the syntax in lisp the same as
you stop reading semi-colons and curly braces in other languages)
Ecksian - 25 minutes ago
But that's prefix notation. RPN is postfix.
breck - 3 minutes ago
I'm a Lisper (and Pythoner) and strongly agree, the first one is
not readable. I would say it's gross. It boggles my mind that
Lispers haven't taken that problem seriously. I have taken it
very seriously and have been working on it for years.I just
started publishing my results.http://breckyunits.com/the-flaw-in-
lisp.htmlWhat I've discovered is that the parentheses are
completely unnecessary in Lisp, and in fact cause much harm by
making Lisp harder to read and maintain in the long run. Drop the
parentheses in Lisp by switching to whitespace/geometry for
syntactic structure and you suddenly have the dream language.Your
example above would be something like: setv result - /
+ 1 3 88 2 8 You might think that looks a little
strange too at first, but the neat thing about that code is you
can write it on a piece of graph paper, draw lines around each
word, connect the indented nodes, and you'd have a tree
visualization of your syntax code without doing a single
transformation of the source.
anaphor - 1 minutes ago
The problem is that it requires all of your functions to have a
fixed arity I think, or at least a lower bound on the arity.
Check out this https://shriram.github.io/p4p/
jwr - 2 hours ago
From a long-time Lisper (Common Lisp, and now Clojure): not, this
is not comfortably readable.That said, I very rarely write code
like this. I tend to split operations over multiple lines, so
that you don't spend so much time digging into and out of nesting
levels. Prefix notation is not ideal for reading math. People
have been writing infix math notation libraries for CL for
exactly this reason.It's not a showstopper, though. Also, I do
find that sometimes having + and < to be of arbitrary arity is
really convenient and makes for nicer code.
cutler - 1 hours ago
It's not merely a matter of syntax or taste. Lisp's code-as-data
and advanced macros are made possible by its s-expressions.
mthomas - 2 hours ago
I find that both are equally (un)readable. However, for
expressions that are that long, I'm inclined to write: (setv
result (-> (+ 1 3 88) (/ 2)
(- 8)))
eanzenberg - 31 minutes ago
((1 + 3 + 88) / 2) - 8 is unreadable? Can I have some of the
crack you're smoking?
[deleted]
cle - 1 hours ago
This is even better than in-fix notation.
jamescostian - 1 hours ago
I am not a lisper, but that looks pretty cool. The non-lisp
ways of writing that would either require adding parens like GP
or writing things like "result /= 2", but that means repeating
"result" or whatever variable many times.
swiley - 2 hours ago
I'd imagine it's like FORTH: If you read enough of it (it only
takes a few days of reading) it becomes clear.
ifelsehow - 2 hours ago
As @jwr says, there are different paradigms in Lisp, such that
you would never really write code like this.
6581 - 2 hours ago
I have been using RPN calculators for all my life (except when I
was forced to use infix calculators in school). Your first
example is at least as readable to me as the second one. Just
read it from inside to outside instead of from left to right.
jonahx - 1 hours ago
> Do you just get used to thisShort answer: yes, and in far less
time than you'd think. The difference between the examples you
cite, specifically, is trivial, and if it's a sticking point for
you I'd suggest (and I'm not trying to be catty at all) that you
broaden your experience with different languages. I mean,
languages like J can become readable with enough experience --
stuff like the above is just a blip on the syntactical radar
screen.Optimizing syntax for readability is a worthy goal, but
experience (both with the language in question and languages in
general) is an almost insurmountable confound here, and
ultimately your goal should be to effortlessly "see past" surface
differences so you can concentrate on the deeper facilities the
language provides for expression.
wodenokoto - 1 hours ago
Will this give me lisp in jupyther notebooks?
mmaul - 1 hours ago
You can already have lisp (common) in jupyter notebooks via cl-
jupyter. Here is an example
https://github.com/mmaul/clml.tutorials/blob/master/CLML-Win...If
you want to use Hy in a note book you will need a jupyter kernel
for it and I belive there is one called hy_kernel
dvdt - 2 hours ago
One fun application: I used Hy to control my liquid handling
robot,https://twitter.com/dtsao/status/891038101706989568
kzisme - 4 hours ago
Shout out to @paultag (Author/Creator of Hy) - he's an awesome guy
who has written some really cool stuff.
boxy_brown - 16 minutes ago
This, Paul is someone I look to as a model open source
contributor in so many
ways.https://twitter.com/nedbat/status/861696880790704128> How
many people can say they have worked with [Sally] Yates, and have
written exemplary Dockerfiles?
gcoda - 1 hours ago
Reason I am trying it - best "hello world" example ever.(print "I
was going to code in Python syntax, but then I got Hy.")
amelius - 1 hours ago
Is this like clojure, but for python instead of java?
yoodenvranx - 4 hours ago
> HyThis must be the worst submission title in the history of HN.
asimjalis - 3 hours ago
It is possibly the shortest.
hk__2 - 2 hours ago
I got curious and I checked; there have been a few one-
character submissions so it?s not the shortest. ?:
https://news.ycombinator.com/item?id=7530548 {:
https://news.ycombinator.com/item?id=7729399 M:
https://news.ycombinator.com/item?id=4367006 In total (at
least in the [fh-bigquery:hackernews.stories] BQ dataset),
there have been 15 non-deleted submissions with a one-character
title.
winter_blue - 4 hours ago
Since Python doesn't support multi-line lambdas, how do they
support the analog in LISP? It's almost necessary for any dialect
of LISP to support lambdas (i.e. functions) that contain a LISP
'do' [1] which lets you group statements. Do they chain together
expressions/statements with continuations or something?[1]
http://www.lispworks.com/documentation/lw60/CLHS/Body/m_do_d...
kbp - 3 hours ago
> It's almost necessary for any dialect of LISP to support
lambdas (i.e. functions) that contain a LISP 'do' [1] which lets
you group statements.> [1] http://www.lispworks.com/documentation
/lw60/CLHS/Body/m_do_d...'do' in most Lisps and Schemes is
essentially an extended for loop, not a blocking construct. Of
course, you could write (do ((once nil t)) ; Scheme: (do
((once #f #t)) (once) (thing-1) (thing-2)
...) or something, but that's silly.The blocking construct is in
CL called PROGN and in Scheme called begin. Lambdas in CL get
what's called an "implicit PROGN" around their bodies, so you can
put however many forms you want inside and the value of the last
is returned. It works the same in modern Scheme lambdas.Calling
PROGN/begin "do" is solely a Clojureism as far as I know.
kazinator - 2 hours ago
> Calling PROGN/begin "do" is solely a Clojureism as far as I
know.Also an ANSI-CL-LOOP-ism: (loop for x in '(1 2 3) do
(print x) (print x)) 1 1 2 2 3 3 Omit the do
and you have a syntax error.
kbp - 2 hours ago
You would have a syntax error with a single PRINT form and no
DO, too.
gkya - 4 hours ago
IIRC in a talk the author said that it just generated a function
with a made-up unique name, like an internal def in another
function.
serhei - 4 hours ago
That's pretty similar to how languages like Scala with higher-
order features translate down to the JVM bytecode (which is
subject to certain restrictions).
kazinator - 2 hours ago
In general, if some target language entity exists in a named
form only, then the corresponding anonymity of those entities
in the source language must be simulated via gensyms.For
instance, the branch targets in a while loop are anonymous,
right? But in the target language, you must have a named
label for the instruction. Solution: machine-generated label.
joejev - 4 hours ago
Python lambdas are just syntactic sugar for creating a function
object. The ast can just build a named function and use it in the
needed expression.
kazinator - 2 hours ago
However, that approach seems rather backwards compared to
having an anonymous function primitive which is used as the
basis for the lambda one-line-only sugar, as well as named
functions (which simply establish a binding between a name and
the anonymous thing).
aoeusnth1 - 1 hours ago
Why should the programmmer care about whether the underlying
function is named or not?
jwdunne - 35 minutes ago
I imagine some kind of analogue to gensym would work there.
The name can be throw away and guaranteed unique in
scope.In fact, a lot of SICP examples have you define a
function within a function with a name like "iter" for TCO
recursion. It'd work like that.Edit: seems like gyka below
confirms that's how it works. I should have read on!
cuspycode - 2 hours ago
I used Hylang to program an Arduino Y?n a few years ago, via cross-
compilation. This was a very nice experience, since it allowed me
to use the great Python ecosystem without having to be limited by
Python the language.
partingshots - 3 hours ago
Now CS61A can finally go back to teaching purely in Scheme again.
asimjalis - 5 hours ago
I have been using Hy as an alternative to Python. It is delightful
to use. Highly recommended.
cheez - 5 hours ago
What kind of projects have you used it for?
asimjalis - 3 hours ago
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.
cutler - 45 minutes ago
There's now Lumo - a Clojurescript binary with its own
embedded Node.js runtime. Script away!
rcarmo - 4 hours ago
My blog/wiki engine is written in an older version of
Hy:https://github.com/rcarmo/sushyI'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.
chuckdries - 4 hours ago
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?
hood_syntax - 3 hours ago
> lightly kissedHow romantic!
gknoy - 4 hours ago
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.
elf_m_sternberg - 3 hours ago
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.
kronos29296 - 3 hours ago
The entire thing is full of puns really too much of puns related to
hy. Cool project. Python joined Erlang and Java with a lisp flavour
of its own with Hy. Hope we get a let expression soon.
udkl - 2 hours ago
While both have their own personalities, has anyone done a side by
side syntax and feature comparison of clojure and Hy ?
ealhad - 1 hours ago
?Keep in mind we?re not Clojure. We?re not Common Lisp. We?re
Homoiconic Python, with extra bits that make sense.? ? Hy Style
GuideThat said, Hy takes a lot from Clojure.
taneem - 5 hours ago
The online demo is amusing/creative: https://try-hy.appspot.com/
nathancahill - 5 hours ago
This is my go-to for toy projects over the last couple years. Great
execution all around. Be aware, if you don't like puns, this isn't
the language for you.
tills13 - 3 hours ago
hy more like why
smaili - 3 hours ago
Excerpt:> Hy is a wonderful dialect of Lisp that's embedded in
Python.> Since Hy transforms its Lisp code into the Python Abstract
Syntax Tree, you have the whole beautiful world of Python at your
fingertips, in Lisp form!
etiam - 3 hours ago
There's even a couple of kernels for IPython/Jupyter. The best I've
seen so far is https://github.com/Calysto/calysto_hyI'd like to
move to Hy for much more of what I currently do in Python, but so
far I've been too lazy to find/create good editor support for it.
For actual projects of some size the loss of context help,
documentation, various completions, etc seems like too high a price
to pay.
thro1237 - 3 hours ago
Also, in terms of useful debug/error messages. That was the
biggest drawback of clojure.
zitterbewegung - 3 hours ago
I think the highest cost is really collaboration with others. If
you ever want help with your project or if people even want to
use it you are dealing with only Hy users and disregarding
regular Python users. I do like the concept of Hy though.
etiam - 1 hours ago
It's restrictive that way, no doubt.On the other hand, I
suspect that as subsets go, Hy programmers would be a good
one.And I'm not sure the impact on getting people to use it
would necessarily be that bad. It's just an extra import hy
away to use modules written in Hy just as usual from Python,
after all.