Функции LISP, которые выполняют как символьные, так и числовые операции над выражениями с использованием +, -, * и /

В настоящее время я работаю над LISP для небольшого проекта и мне нужна серьезная помощь. Это может быть в большей или меньшей степени вопрос новичка, но я совершенно заблудился при написании определенной функции, которая принимает две неоцененные функции и выдает результат в зависимости от того, были ли переменные присвоены или нет.

Примером будет

(setq p1 '(+ x (* x (- y (/ z 2)))))

куда

(evalexp p1 '( (x 2) (z 8) ))
    returns (+ 2 (* 2 (- y 4)))

Моя цель - написать функцию evalexp, но я даже не могу придумать, с чего начать.

Пока у меня есть

(defun evalexp (e b) )

.. не очень много. Если бы кто-нибудь мог помочь или направить меня в правильном направлении, я был бы более чем благодарен.

2 ответа

Решение

Вот полное решение. Это довольно просто, поэтому я опущу полное объяснение. Спросите меня в комментариях, есть ли что-то, что вы сами не можете понять.

(С помощью eval проведение реальной оценки может оказаться не тем, что вы хотите в упражнении / проекте. Посмотрите "мета-круговой переводчик" для другого пути.)

(defun apply-env (exp env)
  (reduce (lambda (exp bdg) (subst (cadr bdg) (car bdg) exp))
          env :initial-value exp))

(defun try-eval (exp)
  (if (atom exp)
      exp
      (let ((exp (mapcar #'try-eval exp)))
        (if (every #'numberp (cdr exp))
            (eval exp)
            exp))))

(defun evalexp (exp env)
  (try-eval (apply-env exp env)))

Вот подсказка, вот как вы можете это сделать (в псевдокоде):

function replace(vars, list):
    for each element of list:
        if it's an atom:
            if there's an association in vars:
                replace atom with value in vars
            else:
                leave atom alone
        else:
            recursively apply replace to the sublist

Когда вы преобразуете это в код на Лиспе, вам наверняка понадобятся некоторые детали.

Другие вопросы по тегам