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

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

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

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

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

textual
Листинг программы
#lang racket
 
(struct env (bindings parent))
 
(define (make-env (parent top-env))
  (env (make-immutable-hasheq) parent))
 
(define (bind e name value)
  (env (hash-set (env-bindings e) name value) (env-parent e)))
 
(define (lookup env name)
  (cond ((hash-has-key? (env-bindings env) name)
         (hash-ref (env-bindings env) name))
        ((env-parent env)
         (lookup (env-parent env) name))
        (else
         (error name "unbound symbol"))))
 
(define (starts-with? exp symbol)
  (and (list? exp)
       (not (null? exp))
       (eq? (car exp) symbol)))
 
(define (def? exp)
  (starts-with? exp 'def))
 
(define (def-name exp)
  (cadr exp))
 
(define (def-value exp)
  (caddr exp))
 
(define (begin? exp)
  (starts-with? exp 'begin))
 
(struct proc (arglist body env))
 
(define (make-proc lambda-exp env)
  (proc (cadr lambda-exp)
        (cddr lambda-exp)
        env))
 
(define (atom? exp)
  (not (cons? exp)))
 
(define (lambda? exp)
  (starts-with? exp 'lambda))
 
(define (eval% exp env)
  (cond ((symbol? exp) (lookup env exp))
        ((atom?   exp)  exp)
        ((def?    exp) (bind env (def-name exp) (eval% (def-value exp) env)))
        ((begin?  exp) (eval-seq (cdr exp) env))
        ((lambda? exp) (make-proc exp env))
        ( else         (apply% (eval% (car exp) env)
                               (map (lambda (x) (eval% x env))
                                    (cdr exp))))))
 
(define (eval-seq seq env)
  (if (null? (cdr seq))
      (eval% (car seq) env)
      (let ((result (eval% (car seq) env)))
        (eval-seq (cdr seq) (if (env? result) result env)))))
 
(define (apply% p args)
  (cond ((procedure? p)  ; built-in primitive
         (apply p args)) ; use built-in apply
        ((proc? p) ; our procedure object
         (let loop ((env     (make-env (proc-env p)))
                    (arglist (proc-arglist p))
                    (args     args))
           (cond ((null? arglist)
                  (if (null? args)
                      (eval-seq (proc-body p) env)
                      (error "too many arguments")))
                 ((null? args)
                  (error "not enough arguments"))
                 ((symbol? arglist)
                  (loop (bind env arglist args) '() '()))
                 (else
                  (let ((name (car arglist))
                        (rest (cdr arglist)))
                    (loop (bind env name (car args)) rest (cdr args)))))))
        (else
         (error 'apply "expected procedure, given: ~a" p))))
 
(define built-ins
  `((+ . ,+)
    (* . ,*)
    (apply . ,apply%)))
 
(define top-env (env (make-immutable-hasheq built-ins) #f))
 
(define-syntax-rule (interp exp ...)
  (displayln (eval% '(begin exp ...) top-env)))
 
(interp
 (def foo (lambda (x) (+ x 1)))
 (def bar (lambda (x) (* x 2)))
 (def main
   (lambda ()
     (def loc (lambda (x) (bar (foo x))))
     (loc (loc 1))))
 (main))
; => 10

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


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

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

9   голосов , оценка 4.333 из 5
Похожие ответы