Стратегия вычислений - в чем ошибка? - Lisp
Формулировка задачи:
Вот такой код
у меня возвращает 103. После детальных разборов я выяснил, что так происходит потому, что весь блок воспринимается как список из 2-х элементов, вычисляется каждый, и первый воспринимается как функция, которую надо применить ко второму. А ради красоты (и может быть так действительно я где-то видел), вычисление первого дефайна, который конструирует лямбду и связывает ее с именем foo в окружении, как раз эту лямбду и возвращает в качестве своего результата! И успешно ее применяет к тройке. В чем мои ошибки понимания стратегии вычислений? Я конечно сейчас сделаю, чтобы результат дефайна возвращал какую-нибудь ересь, чтобы так не происходило. Но мне кажется, что это будет костыль, и есть хорошее стройное решение и трактовка подобных ситуаций.
Листинг программы
- (def foo (lambda (n) (+ n 100)) )
- (+ 1 2)
Решение задачи: «Стратегия вычислений - в чем ошибка?»
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
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д