
Try Hy - proppy
http://try-hy.appspot.com/
======
ninetax
It's a dialect of LISP that's compiled down to Python AST IICR.

Here's more information:
[http://docs.hylang.org/en/latest/tutorial.html](http://docs.hylang.org/en/latest/tutorial.html)

------
paultag
Well done! If anyone wants to learn more:

[http://hylang.org/](http://hylang.org/)

[http://github.com/hylang](http://github.com/hylang)

[http://www.youtube.com/watch?v=ulekCWvDFVI](http://www.youtube.com/watch?v=ulekCWvDFVI)

and a quick 5 minute lightning talk:

[http://youtu.be/1vui-LupKJI?t=16m13s](http://youtu.be/1vui-LupKJI?t=16m13s)

(Creator here)

Hack on!

~~~
kro0ub
Great work, man.

------
agentultra
I did a little presentation on Hy at Pycon Canada earlier this year [1].

Hy has come a ways since then even. Shortly after that talk we added succinct
syntax aliases for QUOTE and QUASIQUOTE. And we added a nice clojure-inspired
core library.

It's a cool little language. Fun to hack on. You could learn a few things if
you do. And I do hope that we can start help creating documentation for the
Python AST module via this project.

[1] [http://pyvideo.org/video/2328/hy-a-lisp-that-compiles-to-
pyt...](http://pyvideo.org/video/2328/hy-a-lisp-that-compiles-to-python)

------
anaphor
So it just desugars into Python? I see there is a section in the documentation
for macros, but there's nothing there. Does it support AST macros right now? I
thought of doing something similar to this except doing some kind of static or
gradual typing (that would be a larger project though).

~~~
paultag
Original author of hylang here - because lisp is homoiconic, you have _real_
macros, not AST macros; although the distinction isn't exactly clear, it's
nice to have them as first-class members of the language, and allow them to
avoid caring about stmt vs expr internally.

Happy to answer questions.

~~~
leifaffles
Can you clarify what you mean about "real" macros vs AST macros? The only
obvious extension to normal AST-style macros I can think of is fexprs, which
re-run the macro procedure on every invocation (rather than once at
read/build/macroexpansion/whatever time).

~~~
paultag
Well, two things.

Firstly, AST visitors in Python (or whatever) are clunky and _lots_ of code to
do what you say. Hell, I think that it's borderline unpythonic.

You have to consider lots of things, such as whether or not you can put an
stmt where you're inserting code, and write a _lot_ of, frankly ugly, Python
code to do it.

Hy macros (and really Lisp macros) that are first-class members of the
language are nice, because they're a lot more clean to write.

In addition, since Hy does some nasty stuff under the hood to generate clean
Python AST, you can do stuff like:

    
    
       (print (if true true flase))
    

(Ok, that's a lie, since it'll do "print True if True else False", but if that
had a (do) around everything, it'd still work by mangling the expression -
just too tired to write that example right now :) )

Fundamentally, a Hy macro _IS_ an AST macro, just on the parsed and tokenized
Hy code (which turns into AST), rather then fiddling with Python AST (which
isn't even a stable interface).

That answer the question? :)

~~~
leifaffles
Yes. Thanks.

------
zaph0d
Very nice. Surface syntax (and some semantics like interop) seem to be heavily
inspired by Clojure :-)

------
girvo
Hy is neat. I love Lisps that "compile" or are embedable within host scripting
languages.

My favourite one to hack on (owing to my PHP ability) is Pharen[0]. Very neat
little Lisp that compiles down to PHP, which is very fun to play with. I
highly suggest giving Hy a go if you're a Pythonista, as you can learn a lot
about programming in general by seeing how these sorts of languages map to the
host. Very fun to hack on, too!

[0]: [http://scriptor.github.io/pharen/](http://scriptor.github.io/pharen/)

------
dmoney
To quote Dark Helmet, "What the hell am I looking at?"

------
vezzy-fnord
Not bad. Could be a very useful tool to teach Python programmers Lisp,
although I don't think Python benefits much from converting its syntax to
sexprs.

~~~
nine_k
If this thing supports macros (and it seems to, see the pipe example in the
tutorial), it may be more powerful than Python — as you'd expect from a Lisp.

~~~
agentultra
It supports macros. It's a lisp-1 and they're not hygienic... but you can hack
away with them.

~~~
aidenn0
and symbols are just strings... that makes writing macros nearly impossible.
CL doesn't need hygenic macros since two symbols with the same name from
different packages are not the same it's hard to accidentally shadow someone
else's definitions.

P.S. The lisp-1 nature of scheme isn't why hygenic macros are important there,
it's really a bit of a red-herring, since macros in common-lisp can (and do)
use (flet) and (labels)

~~~
agentultra
I wouldn't say it's impossible but one should be aware of the issues. And we
can always use more contributors to help make it better.

Hy isn't trying to be CL or Scheme. It is still after all, Python. However a
homoiconic front-end to Python has interesting implications for a language
like Python. Macros in Hy are almost like a template language for Python ASTs.
You could replace the namedtuple implementation with a Hy macro. If Python
didn't have a `with` keyword you could implement it as a Hy macro. I'm sure
there may be more.

Python's not a lisp under the hood. However it does benefit from some of the
superficial features of a homoiconic transpilation. :) </cheeky>

------
andrelaszlo
Apparently without TCO :(

    
    
        File "<input>", line 1, in fac
        File "<input>", line 1, in fac
        File "<input>", line 1, in fac
        RuntimeError: maximum recursion depth exceeded
        =>

------
mattholtom
Heh, recognized reverse polish notation right away. One of the companies I
interviewed at last year had me program an RPN calculator fed by CSV
spreadsheets. Weirdest thing I've made to date by a pretty wide margin.

~~~
sockgrant
They had you do that in the interview?

~~~
mattholtom
Heh, no. It was as a take home coding project (in my earlier and dumber years,
I would never do this now). This was after one business and two technical
phone screeners. Then after they reviewed my code, I was brought in for a
marathon interview lasting from 9:30AM to 6:30PM on a Friday. I left for a
wedding when they started their company wide "pizza and demo night". I imagine
after this was done they pulled out cots and handed out stuffed animals and
blankies to the bro's. In the end, I was so massively frustrated that I forced
myself to nail everything they threw at me just so I could have the
satisfaction of turning down their job offer, which I did.

Thanks matchu for the additional info on RPN. I didn't know about the stack
evaluation benefit, that is very cool.

------
jackhammons
Incredible implementation.

~~~
anaphor
It's not that difficult to parse s-expressions and generate code, which is
what this does.

~~~
haney
For clarity it's generating a python AST which is an object in python. So it's
doing a bit more than just raw syntactic sugar.

------
petercooper
What blew my mind is this actually worked on my iPod Touch and brought up the
keyboard. Usually "dynamic" JavaScript keyboards or games totally fail on
there..

------
hcarvalhoalves
Excellent. I thought what a LISP on top of the Python runtime would be (like
Clojure + JVM), didn't knew this existed already.

------
a3_nm
"(defun f x (x))" gives a Python stack trace.

~~~
chrismonsanto
(defun f (x) (x))

~~~
a3_nm
Yes, I wasn't expecting this wrong syntax to work, just pointing out that the
stack trace looks messy (e.g., leaks the absolute path to the involved Python
file).

------
Sunlis
Finally my knowledge of Scheme comes in handy!

------
talles
Love at first sight with the presentation

------
d0m
I think this is fucking amazing.

------
basyt
effin' finally. now to do some serious lisping!

------
jbeja
This could be the next big thing.

------
jbeja
Is Python really that awesome?

~~~
stolio
SciPy ([http://www.scipy.org/](http://www.scipy.org/)) is really amazing if
that's the corner of programming you're into.

------
derp_dogg
where's cons?

~~~
skrebbel
It only has pros.

~~~
derp_dogg
\+ is overloaded (+ '(1 2) '(3)) => '(1 2 3)

------
mkramlich
A+ for presentation

~~~
ceautery
Indeed; that was fantastic.

~~~
danellis
A little off on Chrome for Linux, though.

[http://i.imgur.com/sC0xuy9.png](http://i.imgur.com/sC0xuy9.png)

~~~
recursive
It seems to depend on the window size. Full-screen 1920x1200 mis-registers it,
but experimenting with different window sizes seem to make it shift around.

------
nlake44
Source: [https://github.com/hylang/tryhy](https://github.com/hylang/tryhy)

------
ravestar
[]+1 = [] 1

[]+[] -> error ...

~~~
twotwotwo
It's using prefix notation, so

    
    
      => (+ [] [])
      []
    

As in Lisp, commas aren't needed to separate list items. []+1 is parsed like
[] followed by positive 1 (+1), which is why it ends up executing even though
it's infix notation passed into a prefix-notation parser.

~~~
ravestar
WAT. I entered 3 items to input: [] + and 1 - this it is evaluated without
error, but was expecting ([] + 1) or something as a result or error. Why there
is no error? Why symbol + and a number are evaluated like + was an operator?

~~~
twotwotwo
The + in +1 is bound tightly to the number like the - in -1. Think of it as
meaning "positive," not addition.

Also, Hy's lexing appears to have an interesting feature where you don't
always need a space to delimit things, so []+1 is automagically broken up into
[] and +1. Here are some other examples where it breaks things up:

    
    
      => []"foo"3"hey"["wakka""wakka"]
      []
      u'foo'
      3
      u'hey'
      [u'wakka', u'wakka']
      
      => (+[1][2][3])
      [1, 2, 3]
    

So without parens, []+1 is like []; +1; in Python and prints out the same
result. With parens, the first token of ([]+1) is treated as a function (as
would be typical in Lisp) so it tries to execute the Python [](+1), and you
get the error that [] isn't callable.

So []+1 ran, but not for the obvious reasons. I'm basically poking at the REPL
like you to try and puzzle this out; if you want to dig further, you could
look at Hy's docs or source or contact the folks that wrote it.

Edit: an additional detail, not sure if it's informative or just confusing--
"\+ 1" is apparently lexed by Hy as two items, not as positive 1:

    
    
      => [] + 1
      []
      Traceback (most recent call last):
      File "<input>", line 1, in <module>
      NameError: name '+' is not defined

