Это будет немного ссылаться на мои два предыдущих вопроса ссылка 1 , ссылка 2 . Я работаю над символическим оценщиком, который станет частью моего проекта по моделированию электрических цепей. Как уже упоминалось ранее, я обратил свое внимание на лямбда-функции и автоматическую генерацию функций.
Задача проста. Давайте определим хеш-таблицу с некоторыми ключами и значениями.
(defparameter *my-hash* (make-hash-table :test #'equal))
(defun get-symbol-var (x)
(gethash x *my-hash*))
(defun symbol-var (x)
(gethash (rest x) *my-hash*))
А вот и основная деривационная функция. Вывод выполняется процессом генерации лямбда-функции с некоторой рекурсией. Это всего лишь образец, поэтому он может выполнять вывод переменных, чисел и произведений двух входных данных.
(defun diff (exp var)
#'(lambda (x) (cond
((numberp exp) 0)
((variablep exp)
(if (same-variablep exp var) 1 0))
((productp exp)
(+ (* (funcall (diff (second exp) var) x) ( eval-exp (third exp)))
(* (funcall (diff (third exp ) var) x) ( eval-exp (second exp))))))))
(defun diff-eval (equation var)
(funcall (diff equation var) (symbol-var var)))
Некоторые полезные определения условий
(defun productp (x)
(eql (car x) '*))
(defun variablep (x)
(eql (car x) 'symbol-var))
(defun same-variablep (v1 v2)
(and (variablep v1) (variablep v2) (equal v1 v2)))
Поскольку некоторые переменные могут выйти из производного цикла, я определил специальную функцию для оценки.
(defun eval-exp (exp)
(cond
((numberp exp) exp)
((variablep exp) (get-symbol-var (rest exp)))
((sump exp) (+ (eval-var-symbol (third exp))
(eval-var-symbol (second exp))))
((productp exp) (* (eval-var-symbol (third exp))
(eval-var-symbol (second exp))))))
Введение некоторых переменных в базу данных
(setf (gethash '(v 1) *my-hash* ) 1)
(setf (gethash '(v 2) *my-hash* ) 23)
(setf (gethash '(v 3) *my-hash* ) 1)
Проверка уравнения d (v1 * v2) / dv1
(setf *equation* '(* (symbol-var v 2) (symbol-var v 1)))
(diff-eval *equation* '(symbol-var v 1))
Правильно ли я делаю это? Может ли это быть сделано более четко LISP.