20 January 2016

A quick translation table from Python to Hy. Hy is a Lisp parser for Python. It parses Lisp code into Python syntax to be executed by the Python interpreter. See also The Nature of Lisp, Casting SPELs in Lisp, Practical Common Lisp.

  • Earmuffs become uppercase (*foo* -> FOO)
  • Dashes become underscores (--name-- -> __name__)

Categories:

assignment:

y = m * x + b
(setv y (+ (* m x) b))

methods:

"  foo  ".strip()
"Hi {}, I'm {}".format("Bill", "Bob")
(.strip "  foo  ")
(.format "Hi {}, I'm {}" "Bill" "Bob")

multi-statement blocks:

if True:
    print ("Side effects rock!")
    print ("Yeah, really!")
(if true
  (do (print "Side effects rock!")
      (print "Yeah, really!")))

classes:

class Cat():
    age = None
    colour = "white"

    def speak(self): print("Meow")

spot = Cat()
spot.colour = "Black"
spot.speak()
(defclass Cat []
  [age None
   colour "white"]

  (defn speak [self] (print "Meow")))

(def spot (Cat))
(setv spot.colour "Black")
(.speak spot)

let creates temporary variables which only exist in its body:

# no Python equivalent
(let [x 5
      y (+ x 1)] (print x y))

Control Flow

if (lispers prefer cond):

if n < 0.0: return "negative"
elif n == 0.0: return "zero"
elif n > 0.0: return "positive"
else: return "not a number"
(if (< n 0.0) "negative"
    (= n 0.0) "zero"
    (> n 0.0) "positive"
    "not a number")

when and unless are simple one-branch conditionals.

while:

while True: print("Hello World")
(while True (print "Hello World"))

for:

for element in collection:
    process(element)
else:
    complete(collection)

for key, value in mydict.items():
    process(key, value)
(for [element collection]
    (process element)
    (else (complete collection)))

(for [(, key value) (.items mydict)]
    (process key value))

try:

try:
    error_prone_function()
except ZeroDivisionError as e:
    print("Division by zero")
else:
    print("no errors")
finally:
    print("all done")
(try
    (error-prone-function)
    (except [e ZeroDivisionError] (print "Division by zero"))
    (else (print "no errors"))
    (finally (print "all done")))

with:

with open("NEWS") as f:
    print(f.read())
(with [f (open "NEWS")]
    (print (.read f)))

Built-In Sequences

built-in sequences:

[1, 2, 3]
(1, 2, 3)
{"cat": "meow", "dog": "bark"}
[1, 2, 3]
(, 1 2 3)
{"cat" "meow" "dog" "bark"}

list, set, dict comprehensions and genexprs:

[x*x for x in range 10 if x%2==0]
{x*x for x in range 10 if x%2==0}
{x:x*x for x in range 10 if x%2==0}
(x*x for x in range 10 if x%2==0)
(list-comp   (* x x) [x (range 10)] (= (% x 2) 0))
(set-comp    (* x x) [x (range 10)] (= (% x 2) 0))
(dict-comp x (* x x) [x (range 10)] (= (% x 2) 0))
(genexpr     (* x x) [x (range 10)] (= (% x 2) 0))
; NOTE only one =

indexing:

mylist[index]
mydict[key]
(get mylist index)
(get mydict key)

item assignment:

mylist[index] = value
mydict[key]   = value
(assoc mylist index value)
(assoc mydict key   value)

variable/index/item deletion:

del dic["foo"]
(del (get dic "foo"))

slicing:

mylist[:]
mylist[3:]
mylist[3:-2]
mylist[3:-2:2]
(cut mylist)
(cut mylist 3)
(cut mylist 3 -2)
(cut mylist 3 -2 2)

Importing

import:

import sys, os.path
from os.path import exists, isdir, isfile
import sys as systest
from sys import *
(import sys os.path)
(import [os.path [exists isdir isfile]])
(import [sys :as systest])
(import [sys [*]])

(import [tests.resources [kwtest function-with-a-dash]]
        [os.path [exists isdir isfile]]
        [sys :as systest])

To import Hy modules in Python, you must first import hy.

To use macros defined in another module, you must use require.

Functions

defining functions:

def foo(x):
    "docstring"
    return x
(defn foo [x]
    "docstring"
    x)

unpacking argument lists:

foo(*args, **kwargs)
foo(**kwargs)
foo(arg0, arg1, arg2, **kwargs)
(apply foo args kwargs)
(apply foo []   kwargs)
(apply foo [arg0, arg1, arg2] kwargs)

lambdas:

map(lambda x: x * x, mylist)
(map (fn [x] (* x x)) mylist)

decorators:

@decorator_fun
def some_function(): ...

@decorator1
@decorator2
def some_function(): ...

@decorator(arg)
def some_function(): ...

@decorator1
@decorator2
def some_function(): ...
(with-decorator decorator-fun
   (defn some-function [] ...)


(with-decorator decorator1 decorator2 ...
   (defn some-function [] ...)

(with-decorator (decorator arg) ..
   (defn some-function [] ...)


#@(decorator1 decorator2
    (defn some-function [] ...))

Macros

defmacro quasiquote unquote unquote-splice

(defmacro infix [code]
  `(~(get code 1) ~(get code 0) ~(get code 2)))

(infix (1 + 1))