[PYTHON] Résumé de l'implémentation de l'interpréteur 7 lignes

Résumé de mon travail / 4ème étape de la feuille de triche. J'ai lu la page Web suivante et j'ai décidé d'écrire le premier interpréteur de 7 lignes (calcul lambda) en Python et dans d'autres langages de programmation. Par conséquent, pour le moment, seules la description Scheme du langage d'origine et la description Python.

(λ x . x) → ((λ x . x)) ((λ x . x) (λ a . a)) → (λ a . a) (((λ f . f) (λ g . g)) (λ a . a)) → ((λ a . a)) (((λ f . (λ x . (f x))) (λ g . g )) (λ a . a)) → ((λ a . a))

Dans cet article, le symbole lambda utilise "/" (au lieu de "λ").

Pour faciliter le portage du travail (?), La structure est divisée en parties suivantes pour chaque langue. Cependant, afin d'éviter la duplication avec des fonctions existantes, ʻeval est le nom de fonction de ʻeval7 et ʻapply est le nom de fonction de ʻapply7.

Schéma (avec explication du contenu du traitement) (R5RS)

Choix de «lecture». Il analyse la phrase et la syntaxe des expressions S (parse).

gosh> (read (open-input-string "(hoge hage (hige (foo bar)) baz)"))
(hoge hage (hige (foo bar)) baz)

ʻAssq` est OK.

gosh> (assq 'a '((a 10) (b 20) (c 30)))
(a 10)

Évaluation faisant partie de la formule. Copiez et collez presque la page Web ci-dessus. Il prend l'expression ʻe et l'environnement ʻenv, si l'expression ʻe est une variable, il récupère la valeur correspondante de l'environnement ʻenv et la renvoie, et si l'expression ʻe est une seule expression lambda, c'est l'environnement ʻenv comme valeur. En dehors de cela, il est considéré comme une liste de la fonction «(car e)» et de la valeur «(cadr e)» donnée à la fonction, et chaque fonction / valeur est auto-évaluée en premier (ordre applicatif). Appelez ʻapply` pour appliquer la fonction.

(define (eval7 e env)
  (cond ((symbol? e)      (cadr (assq e env)))
        ((eq? (car e) '/) (cons e env))
        (else             (apply7 (eval7 (car  e) env)
                                  (eval7 (cadr e) env)))))

Partie d'application de fonction. Copiez et collez presque la page Web ci-dessus. Reçoit la fonction f et la valeur x, associe la variable de fonction(cadr (voiture f))à la valeur x, et la combine avec la valeur non appliquée restante(cdr f)comme environnement. , Appelez la partie d'évaluation de l'expression ʻeval avec la fonction corps expression (cddr (car f)) `.

Par mesure de précaution pour l'implémentation, le côté droit de la période d'expression lambda d'entrée est automatiquement la partie cdr de la paire de points dans Scheme, donc par exemple, «f» est »((/ a. (/ C. d))). Le (cd dr (voiture f)) au moment de) devient (\ c. D) au lieu de (. (/ C. d)) `.

(define (apply7 f x)
  (eval7 (cddr (car f))
         (cons (list (cadr (car f)) x)
               (cdr f))))

Utilisez display tel quel.

gosh> (display '((/ a . a)))
((/ a . a))#<undef>
gosh> (display (eval7 (read) '()))
(((/ f . (/ x . (f x))) (/ g . g )) (/ a . a))
((/ a . a))#<undef>

Python(Python 3,Python2)

Ici read_from_tokens () pakuri. La gestion des erreurs a été perdue.

def readlist(x):
    xl = x.replace('(', ' ( ').replace(')', ' ) ').split()
    def ret(ts):
        t = ts.pop(0)
        if t == '(':
            r = []
            while ts[0] != ')': r.append(ret(ts))
            ts.pop(0)
            return tuple(r)
        else:
            return t
    return ret(xl)
>>> readlist('(hoge hage (hige (foo bar)) baz)')
('hoge', 'hage', ('hige', ('foo', 'bar')), 'baz')

Au début, j'ai pensé à utiliser le type dictionnaire, mais cela semblait gênant au moment de l'évaluation λ, donc je l'ai implémenté en supposant le type taple.

def assoc(k, vl):
    if not vl: return False
    elif vl[0][0] == k: return vl[0]
    else: return assoc(k, vl[1:])
>>> assoc('a', (('a', 10), ('b', 20), ('c', 30)))
('a', 10)

Indice grand succès. Schéma (LISP) (voiture x), (cdr x), (cadr x) est x [0] de Python, x [1:], x [1] Classique (généralement le contraire).

def eval7(e, env):
    if isinstance(e, str): return assoc(e, env)[1]
    elif e[0] == '/':      return (e,) + env
    else:                  return apply7(eval7(e[0], env), eval7(e[1], env))

Le deuxième grand succès en abonnements. La raison de cdddr = [3:] ʻau lieu de cddr=[2:]est de supprimer'.'` (voir l'explication de l'implémentation du schéma).

def apply7(f, x): return eval7(f[0][3:][0], ((f[0][1], x),) + f[1:])

L'inverse de l'entrée. C'est vraiment mon propre travail. Le dernier «[: -1]» est très technique.

def writelist(x):
    def ret(xs):
        r = ('(')
        for t in xs:
            if isinstance(t, tuple):
                r += ret(t)
            else:
                r = r + t + ' '
        r = r[:-1] + ') '
        return r
    return ret(x)[:-1]
>>> writelist(('a', 'b', ('c', 'd'), (('e', 'f'), ('g', 'h'))))
'(a b (c d) ((e f) (g h)))'

Pour Python3 (utilisez ʻinput () `).

>>> print(writelist(eval7(readlist(input()), ())))
(((/ f . (/ x . (f x))) (/ a . a )) (/ b . b))
((/ b . b))

Pour Python2 (utilisez raw_input ()).

>>> print(writelist(eval7(readlist(raw_input()), ())))
(((/ f . (/ x . (f x))) (/ a . a )) (/ b . b))
((/ b . b))

Remarques

Les références

Informations complémentaires sur l'article

modifier l'historique

Recommended Posts

Résumé de l'implémentation de l'interpréteur 7 lignes
Résumé de l'implémentation de la coroutine empilée
[Line / Python] Mémo d'implémentation Beacon
Résumé de l'implémentation de base par PyTorch
Résumé de l'implémentation de scratch 1D-CNN, 2D-CNN par Pytorch
Résumé de la classification et de la mise en œuvre des algorithmes d'apprentissage automatique