Python
( h y )
a.zhlobich@gmail.com
anjensan
Minsk python meetup 2015-02
( недостатки python )
● Плохая многопоточность – GIL
● Медленный
● Явное указание self
● Куцие lambda выражения
● Слабые замыкания
● Отсутствие private
● Сложный рефакторинг
● Болезненный переход на 3
● Нет перегрузки методов
● Неоднородности ООП модели
● …
● Придумайте сами ...
( фатальный недостаток )
>>> from __future__ import braces
SyntaxError: not a chance
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!
( копипаста N
1 )
( копипаста N
2 )
● 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!
( на самом деле )
we do what we must,
because we can
just for fun
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from 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 compiler
Hy AST
Python compiler
Python AST
CPython 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
( основа )
( verb n1
n2
… ns
) → r
Verb:
● Специальная форма
● Функция
● Метод объекта
● Макрос
. , != % %= & &= * ** **= *= + += - | / ~
/= < << <<= <= = > >= >> >>= ^ ^= -= |=
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
( пример N
1 )
(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
( пример N
2 )
(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"))
( пример N
3 )
( киллер-фича )
Метаклассы
Метапрограммирование
вид программирования, связанный с созданием
программ, которые порождают другие программы
как результат своей работы, либо программ,
которые меняют себя во время выполнения
( макросы )
Hy compiler
Python compiler
parser
lexer
macroexpand
S-exprs
ф-ии + спец.формы
+ макросы
S-exprs
ф-ии + спец. формы
run code
at 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
( итого )
( спасибо )

Знакомство с Hy / Андрей Жлобич / Wargaming [Python Meetup 27.02.15]

  • 1.
    Python ( h y) a.zhlobich@gmail.com anjensan Minsk python meetup 2015-02
  • 2.
    ( недостатки python) ● Плохая многопоточность – GIL ● Медленный ● Явное указание self ● Куцие lambda выражения ● Слабые замыкания ● Отсутствие private ● Сложный рефакторинг ● Болезненный переход на 3 ● Нет перегрузки методов ● Неоднородности ООП модели ● … ● Придумайте сами ...
  • 3.
    ( фатальный недостаток) >>> from __future__ import braces SyntaxError: not a chance
  • 5.
    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! ( копипаста N 1 )
  • 6.
    ( копипаста N 2) ● 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!
  • 7.
    ( на самомделе ) we do what we must, because we can just for fun
  • 8.
    from django.shortcuts importget_object_or_404, render from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse from 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
  • 9.
    (import [django.shortcuts [get-object-or-404render]] [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
  • 10.
    ( суть Hy) Hy reader Hy compiler Hy AST Python compiler Python AST CPython VM Python bytecode Hy stdlib
  • 11.
    ( py abstractsyntax 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
  • 12.
    ( hy abstractsyntax 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)
  • 13.
    ( hy.models ) classHyObject(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
  • 14.
    ( большая разница) '(defn my-fun [x y] (+ x (* 2 y))) (defn my-fun [x y] (+ x (* 2 y))) CodeAST (hy)
  • 15.
    ( vs ) 123.4 None "somestring" [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
  • 16.
    ( основа ) (verb n1 n2 … ns ) → r Verb: ● Специальная форма ● Функция ● Метод объекта ● Макрос
  • 17.
    . , !=% %= & &= * ** **= *= + += - | / ~ /= < << <<= <= = > >= >> >>= ^ ^= -= |= 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 ( специальные формы )
  • 18.
    ( 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
  • 19.
  • 20.
    ( пример N 1) (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
  • 21.
    ( пример N 2) (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))
  • 22.
    (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")) ( пример N 3 )
  • 24.
    ( киллер-фича ) Метаклассы Метапрограммирование видпрограммирования, связанный с созданием программ, которые порождают другие программы как результат своей работы, либо программ, которые меняют себя во время выполнения
  • 25.
    ( макросы ) Hycompiler Python compiler parser lexer macroexpand S-exprs ф-ии + спец.формы + макросы S-exprs ф-ии + спец. формы run code at compile time
  • 26.
    ( простейший ) (defmacrounless [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))))
  • 27.
    ( еще один...) (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))
  • 28.
    ( макрос "->") (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))
  • 29.
    ( 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"))
  • 30.
    ( let itbe ) (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)))
  • 31.
    • Hy --это Python на S-exprs • Есть плюсы, есть минусы • Непривычный синтаксис • Местами многословный • Ма-акрос! • Гибкость! • Доступ к Python runtime • Ведь Hy... всего лишь Python ( итого )
  • 32.