Legenda de Títulos:
Exemplo de código no slide
Hy, Python como LISP
Camilo Cunha de Azevedo
- Faço bugs em Python, Clojure e outras linguagens desde 2012.
Link do Github
Link do LinkedIn
- Hy (abreviação de “Hylang”) é uma linguagem de programação criada em 2014 que utiliza a sintaxe LISP e roda na Máquina Virtual Python (Python Virtual Machine - PVM).
- Ela permite aliar a expressividade, declaratividade e simplicidade da sintaxe de LISP com o ecossistema Python.
(print "Hello Hy!")
- LISP é uma família de linguagens de programação (assim como a família ALGOL ou a família C) que engloba diversas linguagens como Scheme, Clojure, Common LISP e Hy.
- Todas elas se relacionam à linguagem LISP escrita por John McCarthy em 1958 sendo a segunda linguagem de alto nível (depois de FORTRAN), a primeira a ter garbage collector, a primeira linguagem interpretada e a primeira linguagem dinâmica.
- Uma característica da linguagem é que todas as expressões são escritas em "formas", uma lista em que o primeiro argumento é uma operação (função) e os valores subsequentes parâmetros.
(operação parametro1 parametro2 ... parametroN)
(+ 5 (* 2 2) 5)
(defn square [x]
(* x x))
(setv mydict {:key1 42 :key2 21})
(get mydict :key1)
5 + 2 * 2 + 5
def square (x):
return x * x
mydict = {"key1": 42, "key2": 21}
mydict["key1"]
Assim como LISP, Hy suporta Orientação a Objetos e Programação Funcional, sendo uma linguagem primeiramente pensada para ser utilizada com programação funcional e declarativa.
(defn mockingbird [f]
(fn [x] (f x)))
def mockingbird(f):
def inner(x):
return f(x)
return inner
(defn quicksort-simple [arr]
(if (<= (len arr) 1) arr
(let [pivot (get arr (// (len arr) 2))
lesser (lfor x arr :if (< x pivot) x)
(+ (quicksort-simple lesser) [pivot] (quicksort-simple greater)))))
(quicksort [3,6,1,9,4,7])
def quicksort(arr):
less = []
pivotList = []
more = []
if len(arr) <= 1:
return arr
else:
pivot = arr[0]
for i in arr:
if i < pivot:
less.append(i)
elif i > pivot:
more.append(i)
else:
pivotList.append(i)
less = quicksort(less)
more = quicksort(more)
return less + pivotList + more
quicksort([3,6,1,9,4,7])
- Os valores literais de Hy são os mesmos de Python.
(type 1)
(type 1.2)
(type 4j)
(type True)
(type None)
(type "hy")
(type b"hy")
- As estruturas de dados e coleções de Hy são as mesmas de Python, porém com syntax sugar para serem declaradas.
(type [1 2 3])
(type {:nome "Camilo" :idade 27})
(type #{1 2 3})
(type #(1 2 3))
- Hy usa a palavra reservada setv para declarar variáveis.
- Em Hy os valores são imutáveis, mas as variáveis não.
- Em Hy pode-se usar alguns caracteres especiais no nome.
(setv nome "Camilo")
nome
(setv nome "Galileu")
nome
(setv nome 5)
nome
(type {:nome "Camilo" :idade 27})
(setx pode-beber? (fn [idade] (> idade 18)))
(pode-beber? 17)
(pode-beber? (get usuario :idade))
- Funções são valores que são ligados a constantes. (Uma função é um valor de uma “variável” como arrow functions para const em JS).
- Existe um syntax sugar que facilita a escrita de funções de uma forma mais legível.
;; (setx <name> (fn [param params...] (...body)))
(setx succ (fn [num] (+ num 1)))
;; (defn <name>
;; [param params...]
(...body))
(defn none?
[value]
(= value value))
-
A sintaxe de uma lista ser (1 2 3) não é por acaso parecido com a sintaxe de uma expressão (operação param params…)
-
Na verdade, quando programamos em LISP todo nosso código é uma árvore de listas que depois são interpretadas. (+ (* 8 8) (* 4 4)), vira:
+ /\ / \ * * /\ /\ 4 4 8 8
- A função "quote" é usada para criar uma representação literal de uma expressão, ela pode ser usada com o syntatic sugar '.
- A expressão não é avaliada, mas sim retornada como uma lista.
- A função “quasiquote” é usada para criar uma represetação literal de uma expressão com valores (como uma f string f”” com interpolação), pode ser escrita com o sugar `.
- O operador "unquote" é usado para inserir uma expressão em uma lista passada com “quasiquote” e retorná-la como literal como a função "quote", pode ser escrita com o sugar ~.
;; Isso é uma expressão + comum em Hy
(+ 1 2 3) ;; => 6
;; Mas podemos usar "quote" para transformá-la em dados
'(+ 1 2 3) ;; => '(+ 1 2 3)
(quote (+ 1 2 3)) ;; => '(+ 1 2 3)
;; Isso pode ser avaliado com a função hy.eval
(hy.eval '(+ 1 2 3)) ;; => 6
;; Porém, por vezes queremos concatenar valores de fora na nossa expressão quote
;; e para isso usamos o quasiquote.
`(+ 1 (+ 1 1) 3) ;; => '(+ 1 (+ 1 1) 3)
;; porém para que essas expresões sejam executadas usamos o operador unquote.
`(+ 1 ~(+ 1 1) 3) ;; => '(+ 1 2 3)
;; Também é possível usar ~@ (unquote-splice) para retirar os valores da lista.
(setv valores '(1 2 3))
`(+ 1 ~@valores) ;; => '(+ 1 1 2 3)
(hy.eval `(+ 1 ~@valores)) ;; => 7
- Macros são funções especiais que permitem a criação de novas formas sintáticas na linguagem.
- Quando uma macro é chamada, ela recebe como argumentos a lista que representa a expressão na qual a macro foi usada.
- A macro retorna uma nova lista, que pode ser avaliada como uma expressão válida em Hy.
(defmacro do-while [condition #* body]
`(do
~body
(while ~condition
~body)))
(setv x 0)
(do-while (< x 5)
(do (print x)
(setv x (+ x 1))))
;; => 0
;; => 1
;; => 2
;; => 3
;; => 4
- Hy suporta a criação, instanciação e uso de Objetos.
- Isso é muito útil para a interação com bibliotecas Python.
- LISP é conhecida por ser multiparadigma e por ser uma das primeiras linguagens a implementar orientação a objetos com o CLOS (Common LISP Object System) sendo uma das primeiras linguagens OOP tendo implementado OOP na metade dos anos 80 (10 anos após a primeira).
(defclass FooBar []
(defn __init__ [self x]
(setv self.x x))
(defn get-x [self]
self.x))
(setv fb (FooBar 15))
(print fb.x) ; => 15
(print (. fb x)) ; => 15
(print (.get-x fb)) ; => 15
(print (fb.get-x)) ; => 15
- À medida que a linguagem cresceu, parte dos macros e funções que foram adicionados na linguagem para facilitar programação funcional foram separados em uma lib chamada “hyrule” que pode ser instalada pelo pip.
(import hyrule.control [loop]
hyrule.iterables [rest])
(defn sum-list [lst]
(loop [[sum 0] [lst lst]]
(if (not lst)
sum
(recur (+ sum (first lst)) (rest lst)))))
(print (sum-list [1 2 3 4])) ;; prints 10
- Possibilidade de utilizar sintaxe LISP com o ecossistema Python.
- Flexibilidade para escolher o paradigma de programação.
- Possibilidade de utilizar bibliotecas Python.
- Facilidade para criação de DSLs.
- Todas as vantagens de Python.
- Curva de aprendizado, principalmente para programadores acostumados com outras linguagens.
- Alguns tipos como símbolos e chaves (keywords) não estão documentados e tendem a ter problemas de conversão.
- Breaking changes ocasionais.
- GIL do Python.
- Todas as desvantagens do Python.
- Vamos aos exemplos.