我遇到了以下F#样本,发现它很有趣。
http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx
Clojure是否有语言/图书馆设施可以轻松完成这样的事情?如果能让事情变得更容易,可以强制使用波兰语表示公式。
谢谢,如果有问题,请告诉我。
答案 0 :(得分:6)
我对Clojure知之甚少,但至少有一些指示。
使F#代码更好的关键特性是代数数据类型上的模式匹配。代数数据类型例如是Expression
类型的声明(用于表示数学表达式),模式匹配是match
构造,用于在实现简化时检查各种已知情况或分化。
我不认为Clojure对模式匹配有任何内置支持,但它可以作为库实现。一个看起来很有趣的库是patter-match module(在Clojars中)。这是一个使用它的例子to implement algebraic evaluator(这与F#文章非常接近)。
F#文章中出现的另一件事是活动模式(允许您声明和重用模式)。我不认为有一个Clojure库,但考虑到语言的灵活性,也应该可以实现它们(但是,它们在F#文章中并不是真正必要的)
答案 1 :(得分:6)
Lisp在符号计算方面有着悠久的历史。见Peter Norvig的the AI case study book。 Lisp提供了许多很棒的语言功能来抽象符号上的常见操作。有时您可以编写非常简洁的代码(比F#更简洁/更简洁)。
像F#这样的静态语言具有强类型系统和对数据类型的方便模式匹配。编译器可以找到类型系统捕获的错误,例如没有考虑一个特例。考虑使用数据的类型也可以减少运行时错误的可能性。 F#中的类型推断也使F#代码非常简洁。
答案 2 :(得分:4)
符号差异化是lisp的首批应用之一!
我写了一篇关于简单符号区分的博客文章。它只处理+和*,但很容易扩展。
这是我在伦敦会议上向初学者介绍clojure的系列文章的一部分,以显示clojure操纵自己的代码是多么容易。
当然可爱的是,完成差异化后,代码就可以编译了!因此,您可以生成差异化的用户输入版本,或生成函数及其衍生物等的宏。
原文在这里,并且语法突出显示:
http://www.learningclojure.com/2010/02/clojure-dojo-4-symbolic-differentiation.html
但是我已经在这里发布了代码,所以你可以看看:
;; The simplest possible symbolic differentiator
;; Functions to create and unpack additions like (+ 1 2)
(defn make-add [ a b ] (list '+ a b))
(defn addition? [x] (and (=(count x) 3) (= (first x) '+)))
(defn add1 [x] (second x))
(defn add2 [x] (second (rest x)))
;; Similar for multiplications (* 1 2)
(defn make-mul [ a b ] (list '* a b))
(defn multiplication? [x] (and (=(count x) 3) (= (first x) '*)))
(defn mul1 [x] (second x))
(defn mul2 [x] (second (rest x)))
;; Differentiation.
(defn deriv [exp var]
(cond (number? exp) 0 ;; d/dx c -> 0
(symbol? exp) (if (= exp var) 1 0) ;; d/dx x -> 1, d/dx y -> 0
(addition? exp) (make-add (deriv (add1 exp) var) (deriv (add2 exp) var)) ;; d/dx a+b -> d/dx a + d/dx b
(multiplication? exp) (make-add (make-mul (deriv (mul1 exp) var) (mul2 exp)) ;; d/dx a*b -> d/dx a * b + a * d/dx b
(make-mul (mul1 exp) (deriv (mul2 exp) var)))
:else :error))
;;an example of use: create the function x -> x^3 + 2x^2 + 1 and its derivative
(def poly '(+ (+ (* x (* x x)) (* 2 (* x x))) 1))
(defn poly->fnform [poly] (list 'fn '[x] poly))
(def polyfn (eval (poly->fnform poly)))
(def dpolyfn (eval (poly->fnform (deriv poly 'x))))
;;tests
(use 'clojure.test)
(deftest deriv-test
(testing "binary operators"
(is (= (let [m '(* a b)] [(multiplication? m) (make-mul (mul1 m) (mul2 m))]) [true '(* a b)]))
(is (= (let [m '(* a b)] [(addition? m) (make-add (add1 m) (add2 m))]) [false '(+ a b)])))
(testing "derivative function"
(is (= (deriv '0 'x) '0))
(is (= (deriv '1 'x) '0))
(is (= (deriv 'x 'x) '1))
(is (= (deriv 'y 'x) '0))
(is (= (deriv '(+ x x) 'x) '(+ 1 1)))
(is (= (deriv '(* x x) 'x) '(+ (* 1 x) (* x 1))))
(is (= (deriv '(* x x) 'y) '(+ (* 0 x) (* x 0))))
(is (= (deriv '(* x (* x x)) 'x) '(+ (* 1 (* x x)) (* x (+ (* 1 x) (* x 1)))))))
(testing "function creation: d/dx (x^3 + 2x^2 + 1) = 3x^2 + 4x "
(let [poly '(+ (+ (* x (* x x)) (* 2 (* x x))) 1)]
(is (= ((eval (poly->fnform poly)) 3) 46))
(is (= ((eval (poly->fnform (deriv poly 'x))) 3))))))
答案 3 :(得分:2)
我没有尝试过,但Clojuratica看起来非常有趣。
答案 4 :(得分:1)
好吧,现在Clojure提供了强大的模式匹配库:
答案 5 :(得分:0)
是的,您现在描述的系统现在存在于Clojure中!正是格里·苏斯曼(Gerry Sussman)的同伴系统 - 和智慧的SICM(经典力学的结构和解释)一书。对于Clojure,它被命名为 sicmutils ,并由Colin Smith移植。
我已在其他地方简要描述过它 - https://stackoverflow.com/a/41646455/4070712 - 但简而言之,肯定是你提到的F#文章提到的四件事,即
以及更多......
1)分化(支持完全偏分化)
> (defn ff [x y] (* (expt x 3)(expt y 5)))
> ((D ff) 'x 'y) ==> (down (* 3 (expt x 2) (expt y 5)) (* 5 (expt x 3) (expt y 4)))
> ;; i.e. vector of results wrt to both variables
NB。支持两种类型的向量," up" " down"以适应协变和逆变表达
2)简化表达:哦,是的......
> (def unity (+ (square sin) (square cos)))
> (unity 'x) ==> 1 ;; yes we can deal with symbols
3)格式化:表达式可以在TeX中呈现,以获得漂亮的显示效果。 我不能在这里轻松地展示这一点,但目前枫树风格的笔记本/工作服正在开发中,使用Clojure" Gorilla"
4)解析:显然。表达式和函数之间的转换是系统的核心部分。
看看https://github.com/littleredcomputer/sicmutils。你甚至不需要Clojure来运行它,你可以使用提供的Java jar文件。