Знакомство с hy / Андрей Жлобич / wargaming [python meetup 27.02.15]
TRANSCRIPT
( недостатки python )
● Плохая многопоточность – GIL● Медленный● Явное указание self● Куцие lambda выражения● Слабые замыкания● Отсутствие private● Сложный рефакторинг● Болезненный переход на 3● Нет перегрузки методов● Неоднородности ООП модели● … ● Придумайте сами ...
In a nutshell, Hy is a Lisp dialect, but one that converts its structure into Python... literally a conversion into Python’s abstract syntax tree!
Or to put it in more crude terms, Hy is lisp-stick on a Python!
( копипаста N1 )
( копипаста N2 )
● A Lisp that feels very Pythonic.● For Lispers, a great way to use Lisp’s crazy
powers but in the wide world of Python’s libraries (why yes, you now can write a Django application in Lisp!)
● For Pythonistas, a great way to start exploring Lisp, from the comfort of Python!
● For everyone: a pleasant language that has a lot of neat ideas!
from django.shortcuts import get_object_or_404, renderfrom django.http import HttpResponseRedirect, HttpResponsefrom django.core.urlresolvers import reversefrom polls.models import Choice, Question
def vote(request, question_id): p = get_object_or_404(Question, pk=question_id) try: sc = p.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): return render(request, 'polls/detail.html', { 'question': p, 'error_message': "You didn't select a choice."}) else: sc.votes += 1 sc.save() return HttpResponseRedirect(reverse('results', args=(p.id,)))
( код Py )
() - 9, [] - 1
(import [django.shortcuts [get-object-or-404 render]] [django.http [HttpResponseRedirect HttpResponse]] [django.core.urlresolvers [import reverse]] [polls.models [Choice Question]])
(defn vote [request question-id] (setv p (get-object-or-404 Question :pk question-id)) (try (setv sc (p.choice-set.get :pk (. request.POST ["choice"]))) (except [KeyError Choice.DoesNotExist] (render request "polls/detail.html" {"question" p "error_message" "You didn't select a choice."})) (else (+= sc.votes 1) (sc.save) (HttpResponseRedirect (reverse "results" :args [p.id])))))
( код Hy )
() - 15, [] - 12
( суть Hy )
Hy reader
Hy compi ler
Hy AST
Py thon c omp i l e r
Python AST
CPy t hon VM
Python bytecode
Hy stdlib
( py abstract syntax tree )
from ast import *
Module([ FunctionDef( 'my_fun', arguments(args=[ Name('x', Param()), Name('y', Param())]), [Return( BinOp( Name('x', Load()), Add(), BinOp( Num(2), Mult(), Name('y', Load()))))], [])])
def my_fun(x, y): return x + 2 * y
AST (py) Code
( hy abstract syntax tree )
from hy import *
HyExpression([ HySymbol('defn'), HySymbol('my-fun'), HyList([ HySymbol('x'), HySymbol('y')]), HyExpression([ HySymbol('+'), HySymbol('x'), HyExpression([ HySymbol('*'), HyInteger(2), HySymbol('y'), ])])])
Code
(defn my-fun [x y] (+ x (* 2 y)))
AST (py)
( hy.models )class HyObject(object):
def replace(self, other): assert isinstance(other, HyObject) for a in ["start_line", "end_line", "start_column", "end_column"]: if not hasattr(self, a) and hasattr(other, a): setattr(self, a, getattr(other, a))
class HyString(HyObject, str): pass
class HySymbol(HyString): pass
class HyInteger(HyObject, int): pass
# ...# HyList, HyExpression, HyDict# HyFloat, HyComplex, HyKeyword, HyCons
( большая разница )
'(defn my-fun [x y] (+ x (* 2 y)))
(defn my-fun [x y] (+ x (* 2 y)))
CodeAST (hy)
( vs )
123.4
None
"some string"
[1, 2, 3]
{"a": 1, "b": 2}
(1, 2, "z")
123.4
nil or null or None
"some string"
[1 2 3]
{"a" 1 "b" 2}
(, 1 2 "z")
Py Hy
. , != % %= & &= * ** **= *= + += - | / ~/= < << <<= <= = > >= >> >>= ^ ^= -= |=
and apply assert assoc break catch continue def defclass defmacro defreader del dict-comp dispatch-reader-macro do eval eval-and-compile eval-when-compile except fn for* genexpr get global if import in is is-not list-comp not not-in or quasiquote quote raise require set-comp setv slice try unquote unquote-splicing while with* with-decorator yield yield-from
( специальные формы )
( vs )
foo(x, y)
True or False
1 + 2
x = 123
"abbc".count("b")
vd[123]
(foo x y)
(or true false)
(+ 1 2)
(setv x 123)
(.count "abbc" "b")
(get vd 123)
Py Hy
( идентефикаторы )
hy_d1ahgkh6g
with_underscores
UPPER_CASE
_CamelCase
__magic__
is_pred
юникод
with-underscores
*upper-case*
-CamelCase
--magic--
pred?
Py Hy
( пример N1 )
(defn my-sum [lst] (setv x 0) (for [e lst] (print ">" e) (+= x e)) x)
(print ":" (my-sum [1 2 3]));; > 1;; > 2;; > 3;; : 6
( пример N2 )
(import os)
(def hidden-files [])(def all-files (os.listdir "."))
(for [f all-files] (when (f.startswith ".") (hidden-files.append f)))
(print "hidden files:" (.join ", " hidden-files))
(defclass Entry [models.Model] [[headline (models.CharField :max-length 255)] [body-text (models.TextField)] [pub-date (models.DateField)] [--str-- (fn [self] (+ "Entry:" self.headline))]])
(-> Entry.objects (.filter :headline--startswith "What") (.exclude :pub-date--gte (datetime.date.today)) (.order "headline") (slice nil 10))
(.save (Entry :headline "Text" :body-text "Some text here"))
( пример N3 )
( киллер-фича )
МетаклассыМетапрограммирование
вид программирования, связанный с созданием программ, которые порождают другие программы как результат своей работы, либо программ, которые меняют себя во время выполнения
( макросы )
Hy compiler
Python compiler
parser
lexer
macroexpand
S-exprsф-ии + спец.формы
+ макросы
S-exprsф-ии + спец. формы
run codeat compile time
( простейший )(defmacro unless [expr &rest body] `(if (not ~expr) (do ~@body)))
(print ">>" (unless (> 1 2) (+= x 1) (+= y 2)))
(print ">>" (if (not (> 1 2)) (do (+= x 1) (+= y 2))))
( еще один... )(import [collections [namedtuple]])
(defmacro deftuple [tname &rest columns] `(def ~tname (namedtuple ~(name tname) ~(list (map name columns)))))
;; ...
(deftuple Point x y)(def a (Point 1 2))
(print a.x (get a 0))
( макрос "->" )(defmacro -> [head &rest rest] (setv ret head) (for [node rest] (if (not (isinstance node HyExpression)) (setv node `(~node))) (.insert node 1 ret) (setv ret node)) ret)
(defmacro my-> [head &rest rest] (if rest `(my-> (~(car (car rest)) ~head ~@(cdr (car rest))) ~@(cdr rest)) head))
( reader macro )
(defreader a [vec] `(numpy.array ~vec))
(print (+ #a [1 2 3 4 5] #a (* [1] 5) ))
(defreader r [expr] `(re.compile ~expr))
(print (.match #r".*" "some string"))
( let it be )
(defmacro let [vars &rest body] `((fn [] ~@(list-comp `(setv ~k ~v) [[k v] vars]) ~@body)))
(let [[x 1] [y 2]] (let [[y 10]] (+= y x) ;; ok (assert (= 11 y)) ;; (+= x 1) - fail! ) (assert 3 (+ x y)))
• Hy -- это Python на S-exprs• Есть плюсы, есть минусы• Непривычный синтаксис• Местами многословный• Ма-акрос!• Гибкость!• Доступ к Python runtime• Ведь Hy... всего лишь Python
( итого )