Cool Lisp écrit en Python: Hy

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.

Motivation

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.

Installation Hy

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?

Visite de Hy Hitomi

Voyons de quel genre de langage il s'agit.

Syntaxe de base

Structure de données

;;;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')

une fonction

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.

Accéder aux fonctions Python

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.

macro

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.

Accéder à Python depuis Hy

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]

Résumé

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

Cool Lisp écrit en Python: Hy
Gacha écrit en Python -BOX Gacha-
Programme de diagnostic de compatibilité écrit en python
Logique gacha simple écrite en Python
Code de vérification de la série Fourier écrit en Python
Test de stress avec Locust écrit en Python
Probabilité de transition de la chaîne de Markov écrite en Python
Quadtree en Python --2
Python en optimisation
CURL en Python
Métaprogrammation avec Python
Python 3.3 avec Anaconda
Géocodage en python
SendKeys en Python
Méta-analyse en Python
Unittest en Python
Époque en Python
Discord en Python
Allemand en Python
DCI en Python
tri rapide en python
nCr en python
N-Gram en Python
Programmation avec Python
Plink en Python
Constante en Python
FizzBuzz en Python
Sqlite en Python
Étape AIC en Python
LINE-Bot [0] en Python
CSV en Python
Assemblage inversé avec Python
Réflexion en Python
Constante en Python
nCr en Python.
format en python
Scons en Python 3
Puyopuyo en python
python dans virtualenv
PPAP en Python
Quad-tree en Python
Réflexion en Python
Chimie avec Python
Hashable en Python
DirectLiNGAM en Python
LiNGAM en Python
Aplatir en Python
Aplatir en python
Introduction à la vérification de l'efficacité Chapitre 3 écrit en Python
Introduction à la vérification de l'efficacité Chapitre 2 écrit en Python
Liste triée en Python
AtCoder # 36 quotidien avec Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python
Daily AtCoder # 18 en Python
Modifier les polices en Python
Motif singleton en Python
Opérations sur les fichiers en Python