Hygiène r7rs macro: retour deuxième valeur d'expression

voix
0

J'apprends actuellement quelques r7rs et je suis en train de mettre en œuvre une macro « commencer » comme suit:

(begin0 expr0 expr1 ... expr2)

Avec expr étant une expression régulière (comme (set! X (+ x 1)))

Et begin0 comme une macro qui permet d'évaluer toute l'expression, mais revenir seulement le résultat de Expr1.

Par exemple :

(let ((year 2017))
(begin1 (set! year (+ year 1))
  year
  (set! year (+ year 1))
  year)) 

Il musts retour 2018

J'ai créé une première fonction commence:

(define-syntax begin0
 (syntax-rules ()
  ((begin-0 body-expr-0 body-expr-1 ...)
   (let ((tmp body-expr-0)) body-expr-1 ... tmp))))

Et maintenant, je suis en train de comprendre comment je peux faire pour retourner la valeur du « corps-expr-1 »? Je l'ai fait le code suivant, mais il dit que je manque quelques points de suspension et je ne comprends pas comment le faire.

(define-syntax begin1
  (syntax-rules ()
    ((begin1 body-expr-0 body-expr-1 ... body-expr-2)
     (let ((tmp body-expr-0) body-expr-1 ... tmp)
       (cond (eq? tmp body-expr-1)
              (begin . tmp))))))

J'espère que cela est assez compréhensible, merci pour les réponses.

Créé 27/11/2018 à 15:14
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
2

Cela peut être fait, mais la macro va interférer ce que vous ne pouvez pas faire toutes les choses avec begin1comme avec begin.

(define-syntax begin1
   (syntax-rules ()
     ((_ expr0 expr1 exprn ...)
      (begin
        expr0
        (let ((result expr1))
          exprn ...
          result)))))

Le code qui ne fonctionne pas est la suivante:

(begin1
  (define global1 10)
  test3
  (define global2 20))

La raison est évidente. Il se développe à:

(begin1
  (define global1 10)
  (let ((result~1 test3))
    (define global2 20)
    result~1))

Le second definesera changé à une letrectelle que la variable global2est uniquement disponible pour la durée de la let. Je n'ai pas de solution pour cela car il vous oblige à être en mesure de faire globale defined'une fermeture.

begin1est caractéristique plutôt étrange. Racket et peut - être d' autres dialectes Scheme nous begin0qui renvoie le résultat de la première expression. Ceci est très utile. par exemple. voici un compteur:

(define (get-counter from)
  (lambda ()
    (let ((tmp from))
      (set! from (+ from 1))
      tmp)))

Et avec begin0:

(define (get-counter from)
  (lambda ()
    (begin0 
      from
      (set! from (+ from 1)))))

En raquette begin0est une primitive. Il est donc une forme supportée dans le programme élargi et donc pleinement mis en œuvre en C, tout comme begin..

Créé 27/11/2018 à 22:22
source utilisateur

voix
-1

Donc, j'ai trouvé un moyen possible de le faire, je ne l'ai pas si nous pourrions poser une condition sur la valeur immédiate:

(define-syntax begin1
  (syntax-rules ()
    ((begin1 body-expr-0 body-expr-1 body-expr-2 ...)
       (if body-expr-1
          (write body-expr-1)))))
Créé 27/11/2018 à 16:12
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more