Стратегия вычислений - в чем ошибка? - Lisp

Узнай цену своей работы

Формулировка задачи:

Вот такой код
Листинг программы
  1. (def foo (lambda (n) (+ n 100)) )
  2. (+ 1 2)
у меня возвращает 103. После детальных разборов я выяснил, что так происходит потому, что весь блок воспринимается как список из 2-х элементов, вычисляется каждый, и первый воспринимается как функция, которую надо применить ко второму. А ради красоты (и может быть так действительно я где-то видел), вычисление первого дефайна, который конструирует лямбду и связывает ее с именем foo в окружении, как раз эту лямбду и возвращает в качестве своего результата! И успешно ее применяет к тройке. В чем мои ошибки понимания стратегии вычислений? Я конечно сейчас сделаю, чтобы результат дефайна возвращал какую-нибудь ересь, чтобы так не происходило. Но мне кажется, что это будет костыль, и есть хорошее стройное решение и трактовка подобных ситуаций.

Решение задачи: «Стратегия вычислений - в чем ошибка?»

textual
Листинг программы
  1. #lang racket
  2.  
  3. (struct env (bindings parent))
  4.  
  5. (define (make-env (parent top-env))
  6.   (env (make-immutable-hasheq) parent))
  7.  
  8. (define (bind e name value)
  9.   (env (hash-set (env-bindings e) name value) (env-parent e)))
  10.  
  11. (define (lookup env name)
  12.   (cond ((hash-has-key? (env-bindings env) name)
  13.          (hash-ref (env-bindings env) name))
  14.         ((env-parent env)
  15.          (lookup (env-parent env) name))
  16.         (else
  17.          (error name "unbound symbol"))))
  18.  
  19. (define (starts-with? exp symbol)
  20.   (and (list? exp)
  21.        (not (null? exp))
  22.        (eq? (car exp) symbol)))
  23.  
  24. (define (def? exp)
  25.   (starts-with? exp 'def))
  26.  
  27. (define (def-name exp)
  28.   (cadr exp))
  29.  
  30. (define (def-value exp)
  31.   (caddr exp))
  32.  
  33. (define (begin? exp)
  34.   (starts-with? exp 'begin))
  35.  
  36. (struct proc (arglist body env))
  37.  
  38. (define (make-proc lambda-exp env)
  39.   (proc (cadr lambda-exp)
  40.         (cddr lambda-exp)
  41.         env))
  42.  
  43. (define (atom? exp)
  44.   (not (cons? exp)))
  45.  
  46. (define (lambda? exp)
  47.   (starts-with? exp 'lambda))
  48.  
  49. (define (eval% exp env)
  50.   (cond ((symbol? exp) (lookup env exp))
  51.         ((atom?   exp)  exp)
  52.         ((def?    exp) (bind env (def-name exp) (eval% (def-value exp) env)))
  53.         ((begin?  exp) (eval-seq (cdr exp) env))
  54.         ((lambda? exp) (make-proc exp env))
  55.         ( else         (apply% (eval% (car exp) env)
  56.                                (map (lambda (x) (eval% x env))
  57.                                     (cdr exp))))))
  58.  
  59. (define (eval-seq seq env)
  60.   (if (null? (cdr seq))
  61.       (eval% (car seq) env)
  62.       (let ((result (eval% (car seq) env)))
  63.         (eval-seq (cdr seq) (if (env? result) result env)))))
  64.  
  65. (define (apply% p args)
  66.   (cond ((procedure? p)  ; built-in primitive
  67.          (apply p args)) ; use built-in apply
  68.         ((proc? p) ; our procedure object
  69.          (let loop ((env     (make-env (proc-env p)))
  70.                     (arglist (proc-arglist p))
  71.                     (args     args))
  72.            (cond ((null? arglist)
  73.                   (if (null? args)
  74.                       (eval-seq (proc-body p) env)
  75.                       (error "too many arguments")))
  76.                  ((null? args)
  77.                   (error "not enough arguments"))
  78.                  ((symbol? arglist)
  79.                   (loop (bind env arglist args) '() '()))
  80.                  (else
  81.                   (let ((name (car arglist))
  82.                         (rest (cdr arglist)))
  83.                     (loop (bind env name (car args)) rest (cdr args)))))))
  84.         (else
  85.          (error 'apply "expected procedure, given: ~a" p))))
  86.  
  87. (define built-ins
  88.   `((+ . ,+)
  89.     (* . ,*)
  90.     (apply . ,apply%)))
  91.  
  92. (define top-env (env (make-immutable-hasheq built-ins) #f))
  93.  
  94. (define-syntax-rule (interp exp ...)
  95.   (displayln (eval% '(begin exp ...) top-env)))
  96.  
  97. (interp
  98.  (def foo (lambda (x) (+ x 1)))
  99.  (def bar (lambda (x) (* x 2)))
  100.  (def main
  101.    (lambda ()
  102.      (def loc (lambda (x) (bar (foo x))))
  103.      (loc (loc 1))))
  104.  (main))
  105. ; => 10

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4.333 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы