GOPHERSPACE.DE - P H O X Y
gophering on hngopher.com
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.