#lang scheme
(require mzlib/defmacro)
(define intervalo
  (lambda (a b)
    (if (> a b)
        '()
        (cons a
              (intervalo (add1 a) b))) ))

;;Ejercicios del capítulo Expansiones sintácticas
(let
    ((t-inicial (current-milliseconds)))
  (intervalo 1 1000)
  (- (current-milliseconds) t-inicial) )

;;el problema de medir el tiempo que tarda un procedimiento en ejecutarse
(define tiempo_de
  (lambda (proc)
    (printf "Valor de proc = ~a~n" proc)
    (let ((t-inicial (current-milliseconds)))
      (proc)
      (- (current-milliseconds) t-inicial)) ))
;;tiempo-de como una expansión sintáctica
(define-syntax tiempo-de
  (syntax-rules ()
    [
     (tiempo-de proc)
     (let ((t-inicial (current-milliseconds)) )
       proc
       (- (current-milliseconds) t-inicial)
       )
     ]
    ))
;;Otros ejercicios
;;Definición de let = hacer

(let ((a 12)
      (b 10)
      (mensa "El producto de ~a por ~a es: ~a~n")
      )
  (printf mensa a b (* a b))
  )
;;en términos de una expresión lambda.
(define-syntax hacer
  (syntax-rules ()
    [
     (hacer ((var valor) ...) expr1 expr2 ...)
     ((lambda (var ...) expr1 expr2 ...) valor ...)
     ]
    ))

(hacer ((a 12)
        (b 10)
        (mensa "El producto de ~a por ~a es: ~a~n")
        )
       (printf mensa a b (* a b)) )
;;Definción de make-proc
(define-syntax make-proc
  (syntax-rules ()
    [
     (make-proc (arg ...) expr ...)
     (lambda (arg ...) expr ...)
     ]
    [
     (make-proc (arg ... . opc) expr ...); pattern
     (lambda (arg ... . opc) expr ...); template
     ]
    [
     (make-proc arg expr ...); pattern
     (lambda arg expr ...); template
     ]
    ))
;;
(define suma2
  (make-proc (n)
    (+ 2 n) ))

(define añade1
  (make-proc (n . x)
    (add1 
     (apply + (cons n x))) ))

(define suma
  (make-proc arg
    (apply + arg) ))
;;el ejemplo del si
(define-syntax si
  (syntax-rules ()
    [
     (si test acciones-t acciones-f)
     (if
       test
       `(begin ,@acciones-t)
       `(begin ,@acciones-f))
     ]
    ))
    
(define prueba-si
  (lambda (n)
    (si (even? n)
        ((printf "par") n)
        ((printf "impar") n)) ))

(prueba-si 6)
(define-macro si
  (lambda (test acciones-t acciones-f)
    `(if
      ,test
      (begin ,@acciones-t)
      (begin ,@acciones-f))
    ))
    
(define prueba-si
  (lambda (n)
    (si (even? n)
        ((printf "par") n)
        ((printf "impar") n)) ))