Знакомство с hy / Андрей Жлобич / wargaming [python meetup 27.02.15]

32
Python ( hy ) [email protected] anjensan Minsk python meetup 2015-02

Upload: python-meetup

Post on 15-Jul-2015

208 views

Category:

Software


0 download

TRANSCRIPT

Python

( h y )

[email protected]

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!

( копипаста 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!

( на самом деле )

we do what we must, because we can

just for fun

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

( основа )

( verb n1

n2 … n

s ) → 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

( пример 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

( итого )

( спасибо )