#lang play ;; timer (36.1.1 del PLAI) ; no funciona (evaluación temprana!) (define (my-time1 e) (let ((begin-time (current-milliseconds))) (begin e (- (current-milliseconds) begin-time)))) (my-time1 (expt 2 10000000)) ; ahora si, pero hay que pasar una lambda "a mano" (define (my-time2 e-thunk) (let ((begin-time (current-milliseconds))) (begin (e-thunk) (- (current-milliseconds) begin-time)))) (my-time2 (λ () (expt 2 100000000))) ; usando una macro: substitución textual (defmac (my-time e) (let ((begin-time (current-milliseconds))) (begin e (- (current-milliseconds) begin-time)))) (my-time (expt 2 100000000)) ;; exploren lo que hace el macro stepper ;; let como una macro (36.1.2 del PLAI) (defmac (my-let-1 (var val) body) ((λ (var) body) val)) (my-let-1 (x 3) (+ x 4)) ; multiples argumentos usando elipsis "..." (defmac (my-let ((var val) ...) body) ((λ (var ...) body) val ...)) (my-let ((x 3) (y 4)) (+ x y)) (my-let () 3) ;; defmac no soporta macros recursivas (36.1.3 del PLAI, pero da lo mismo ;; no lo vamos a necesitar para OOP) ;; keywords (36.1.4 del PLAI) (defmac (cond2 (t e1) (else e2)) (if t e1 e2)) ; usando 'else' (cond2 ((even? (current-seconds)) 'even) (else 'odd)) ; podemos poner cualquier cosa en vez de else, pero no es la idea! (cond2 (false 'even) ((/ 1 0) 'odd)) ; declaramos con defmac que 'else' es un keyword (defmac (cond3 (t e1) (else e2)) #:keywords else (if t e1 e2)) ; ahora lo siguiente es un error de sintaxis #;(cond3 (false 'even) ((/ 1 0) 'odd)) ;; disjunción (36.1.5 del PLAI) ; or es una macro. Nuestra primera definición: (defmac (my-or e1 e2) (if e1 e1 e2)) ; no se comporta como esperado: estamos duplicando computación (my-or (begin (write "hola") #t) (/ 1 0)) ; ahora si (defmac (my-or2 e1 e2) (let ([result e1]) ; e1 se ejecutará una sola vez (if result result e2))) ; bien (my-or2 (begin (write "hola") #t) (/ 1 0)) ;; hygiene (36.2 del PLAI) ; que da esto? haganlo a mano, luego observen el resultado ; y usen el macro stepper para entender (let ((result true)) (my-or2 false result))