Ceci est l'article du 7ème jour du Calendrier de l'Avent iRidge.
Cet article présente Hy, un dialecte Lisp implémenté en Python.
Je suis tanaka.lisp, un ingénieur côté serveur d'Iridge Co., Ltd. Je veux voir le monde du web et Python, et je travaille pour la société Python Iridge.
Du coup, la langue que j'aime tant est Common Lisp. Dans mon entreprise, je lis et écris exclusivement Python, mais comme Python n'est pas Lisp, je suis à la merci de l'indentation automatique, et ʻif pred1 et pred2: ... à ʻif (et pred1 pred2): ... J'ai constamment du mal à écrire ». Des symptômes de sevrage propres à Lisper peuvent apparaître. J'ai commencé à penser aux expressions S, à rechercher sur Google "Nom de la fonction Hyperspec
", et à taper des expressions S dans Emacs. En fin de compte, c'est une idée mystérieuse que __Python devienne Lisp, ce qui me traverse la tête pendant les heures de bureau.
Oh, si Python était une expression S. Si vous pouviez écrire une expression S en chevauchant l'énorme groupe de bibliothèques standard de Python comme Where's Language. Oh, oh!
Mais il y a. Une langue si rêveuse et cool.
Hy
Hy est un dialecte Lisp écrit en Python.
Il a une syntaxe fortement influencée par Clojure, et si vous vous perdez dans le Hy Style Guide, l'ordre est Python> Clojure> Common Lisp
. Alors, suivez les coutumes de cette langue.
De plus, il est possible d'interopérer avec Python comme Clojure, et il semble que l'application Django peut être écrite en Hy. Oh, n'est-ce pas bon pour Hy? ??
Au fait, Haskell est célèbre comme langue de calmar, mais la mascotte de Hy semble être le calmar. Vous êtes un calmar. La documentation Tutoriel de trois minutes est la plus intéressante et je vous recommande de la lire. J'ai été assommé avec ça.
Installons-le. Ici, installez-le dans l'environnement virtualenv [^ 1].
[^ 1]: Au fait, il semble qu'il soit enregistré dans le dépôt apt d'ubuntu avec le nom python-hy
.
Commencez par créer un environnement venv,
$ virtualenv venv
# ...Beaucoup de sortie
$ cd venv
$ source ./venv/bin/activate
Ensuite, installez depuis github avec pip.
(venv) $ pip install git+https://github.com/hylang/hy.git
# ...Beaucoup de sortie
Bonjour pour démarrer le REPL est après.
(venv) $ hy
hy 0.11.0+320.g5b87932 using CPython(default) 2.7.12 on Linux
=> (print "Hy!")
Hy!
=>
C’est facile, non?
Voyons de quel genre de langage il s'agit.
;;;Valeur numérique et valeur de vérité
=> 42
42L
=> False
False
;;;Chaîne
=> "forty two"
u'forty two'
Tout d'abord, la structure de données qui peut être utilisée en Python peut être utilisée presque telle quelle. Cependant, il semble que l'écriture «,» ou «:» ou delimita est interdite.
;;;liste. `,`N'écris pas
=> ["life" "universe" "everything"]
[u'life', u'universe', u'everything']
;;;dictionnaire.Cela ne nécessite pas non plus de delimita
=> {"arthor" "dent" "ford" "prefect"}
{u'arthor': u'dent', u'ford': u'prefect'}
Et voici les types de données propres à Lisp. Il semble étrange que l'affichage du symbole soit une chaîne de caractères Unicode.
;;;symbole.L'affichage est une chaîne de caractères, mais le type est un symbole correctement
=> 'marvin
u'marvin'
=> (type 'marvin)
<class 'hy.models.symbol.HySymbol'>
;;mot-clé
=> :deep-thought
u'\ufdd0:deep-thought'
;;Des symboles toujours différents des autres
=> (gensym)
u':G_1236'
Et comment, il n'y a pas de «nul»! Ah, mon Dieu, comment écrire une liste vide?
;;;non nul!
=> nil
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'nil' is not defined
Dieu "Vous devriez utiliser ()
! "
Je "je vois!"
=> ()
[]
En fait, il semble que même la notation de liste traditionnelle de Lisp puisse ** parfois devenir une liste Python **.
=> '(a b c)
(u'a' u'b' u'c')
=> (cons 'googolplex (cons 'star (cons 'thinker ())))
[u'googolplex', u'star', u'thinker']
Et contre. Il semble que le père de Lisp, John McCarthy, l'ait prononcé Corns.
=> (cons 'arther 'dent)
(u'arther' . u'dent')
;;;Il est acceptable d'écrire par paires de points et de citer
=> '(arther . dent)
(u'arther' . u'dent')
Puisque Hy est un langage Lisp, les appels de fonction sont écrits en notation polonaise.
;;;Concaténation de chaînes
=> (+ "forty" " " "two")
u'forty two'
;;;Quatre règles
=> (+ 1 (* 5 8) 1)
42L
La définition de la fonction ressemble à celle de Clojure. C'est le sentiment habituel lorsque je tape simplement «defun» et que je suis confus.
=> (defn factorial [n]
... (if (<= n 0)
... 1
... (* n (factorial (- n 1)))))
=> (factorial 10)
3628800L
À propos, la liste est la syntaxe sucrée de Cons. Le code Lisp est écrit dans une liste. Vous devriez donc pouvoir écrire du code par contre. En Common Lisp, même si vous écrivez un programme avec des paires de points, il sera lu correctement, mais ...
=> (print . ("forty" . ("two" . ())))
forty two
Oh! Je vais le faire! Cela a ouvert la voie à l'obscurcissement.
Comme exemple d'utilisation de l'abondante bibliothèque standard de Python, essayez Exemples de communication utilisant httplib avec Hy.
;;;importer.de peut également être importé
=> (import httplib)
=> (setv conn (httplib.HTTPSConnection "www.python.org"))
=> (conn.request "GET" "/")
=> (setv res (conn.getresponse))
=> (print res.status res.reason)
200 OK
Lisez-le simplement comme formule S et c'est fait. C'est votre chance de déplacer un script écrit en Python vers Hy.
Maintenant, assurez-vous que Hy n'est pas seulement familier avec Python, c'est aussi un compagnon Lisp. Pour ceux qui ne sont pas Lisper, les macros ici ne sont pas des macros C, ce sont celles qui manipulent des arbres de syntaxe abstraite. Rust, Nim, Scala, etc. ont cette fonction. Au fait, Hy [a déjà une macro anaphorique] en tant que module contributeur (http://docs.hylang.org/en/latest/contrib/anaphoric.html).
A titre d'exemple, pour le moment, je pensais que les macros anaphoriques étaient appropriées car les bénéfices sont faciles à comprendre. Une macro anaphorique, par exemple, vous permet de faire référence à la valeur d'une expression dans la partie conditionnelle d'une instruction if par derrière. Pour plus de détails, voir [Chapitre correspondant de On Lisp](http: //www.asahi-net. Veuillez également lire or.jp/~kc7k-nd/onlispjhtml/anaphoricMacros.html).
Pour le moment, je vais l'implémenter en copiant depuis On Lisp et essayer de l'utiliser.
=> (defmacro aif [test-form then-form &optional else-form]
... `(let [it ~test-form]
... (if it ~then-form ,else-form)))
=> (aif (+ 1 2)
... (print 'cheese it it))
cheese 3 3
Vous pouvez vous référer au résultat de l'évaluation de l'expression conditionnelle de l'expression if (ici, ʻaif) dans ʻit
. Voyons comment l'expression est convertie
;;;La sortie est formatée à la main pour une visualisation facile
=> (macroexpand '(aif (+ 1 2)
... (print 'cheese it it)))
((u'fn' [](u'setv' u'it' (u'+' 1L 2L))
(u'if' u'it'
(u'print' (u'quote' u'cheese') u'it' u'it')
u',else_form')))
Le symbole est affiché sous forme de chaîne Unicode, ce qui est gênant, mais il semble bon.
Ce qui me rend heureux à ce sujet
--Une valeur déjà calculée (en cas de branchement conditionnel) peut être utilisée
C'est un bon point.
À titre d'exemple, considérons le cas où une expression conditionnelle est une expression qui prend beaucoup de temps.
=> (reduce (fn [a b](+ a b)) (range 1 1000000000))
499999999500000000
J'ai essayé de trouver cette formule pour le moment ** REPL est resté silencieux pendant environ une minute: sanglot: **. Lorsque vous souhaitez utiliser ce résultat plusieurs fois
(aif (reduce (fn [a b](+ a b)) (range 1 1000000000))
(print (+ it it))
C'est une dimension qui peut éviter de multiples calculs. C'est une histoire que vous devez l'assigner à une variable locale, mais si vous écrivez une macro anaphorique, la création et l'affectation de la variable locale se feront automatiquement dans les coulisses.
Finalement. Vous pouvez convertir du code Hy en code Python. En faisant cela, vous pouvez éliminer le danger de Hy qui est détenu par REPL ~ ~ lors du développement, écrire en Hy et convertir en Python lors de la validation de ~ ~.
Si vous essayez, la surcharge de l'analyse réelle sera réduite, ou il n'y aura pas de décalage jusqu'à ce que le résultat soit renvoyé.
(venv) $ cat upto.hy
(defn up-to-n [n]
(list-comp n (n (range n)) (= (% n 2) 0)))
(print (up-to-n (integer (raw-input "input number: "))))
# upto.Convertir hy
(venv) $ hy2py upto.hy > upto.py
#Résultat de la conversion
(venv) $ cat upto.py
from hy.core.language import integer, range
def up_to_n(n):
return [n for n in range(n) if ((n % 2L) == 0L)]
print(up_to_n(integer(raw_input(u'input number: '))))
(venv) $ python upto.py
input number: 10
[0, 2, 4, 6, 8]
Introduction du dialecte Lisp Hy écrit en Python.
--L'installation est facile avec pip
--Hy syntaxe est simple, pratique et expression S
--Hy peut accéder aux actifs Python
--Hy a le pouvoir de méta-programmation de Lisp
--Hy code peut être converti en code Python pour plus rapide
C'est une impression que j'ai essayé de l'écrire en le touchant que c'est une langue assez bien faite.
Cet article devait initialement être publié il y a un an [^ 2]. Cependant, après tout, quand j'ai appris à connaître le monde de Python et que je l'ai touché, je pouvais deviner le contexte de la façon dont Hy était fait. Il se peut que le moment soit venu de s'habituer à Python.
[^ 2]: Je pensais l'annoncer dans le LT interne, mais cela me paraît difficile de le faire dans cet article LT ...
Je pense que Hy en lui-même est un assez bon langage, donc les frères Lisper qui sont engagés dans l'industrie Python devraient envisager de l'introduire lorsqu'ils disent: "Je dois utiliser Python, mais la syntaxe n'est pas de style S." Pourquoi ne pas l'essayer?
Recommended Posts