2010年10月31日星期日

Definitions of Imperative & Functional Programming from SICP

Programming without any use of assignments is accordingly known as functional programming.

In contrast to functional programming, programming that makes extensive use of assignment is known as imperative programming.

2010年10月30日星期六

求对数

下面是求以 1.12 为底,2.7 的对数。本方法极其低效,仅仅标记一下以备以后参考。

(ns t
(:require [clojure.contrib.generic.math-functions :as math]))

(defn abs [x]
(if (< x 0) (* -1 x) x))

(defn close-enough? [delta]
#(< (abs (- %1 %2)) delta))

(defn calc-log [lg lg-level acc-stack]
(let [acc (math/pow 1.12 lg)
close? (close-enough? 0.00000000000000000001M)
lg-inc (/ 1 (math/pow 10 lg-level))
finer-lg-inc (/ 1 (math/pow 10 (inc lg-level)))]
(if (close? acc 2.7)
lg
(if (> acc 2.7)
(recur (+ (- lg lg-inc) finer-lg-inc) (inc lg-level) acc-stack)
(recur (+ lg lg-inc) lg-level (conj acc-stack acc))))))

(println (calc-log 1 0 []))

2010年10月26日星期二

空间

《Structure and Interpretation of Computer Programs》中提到,“The ability to create pairs whose elements are pairs is the essence of list structure's importance as a representational tool. We refer to this ability as the closure property of cons.”这话表面上是说 cons 作为 LISP 的核心,能够把自己产生的 pair 作为 cons 的参数进而去产生新的组合 pair,是列表数据结构在表示上非常本质的东西。“closure property”我倾向于翻译成封闭性。因为在代数中,给定 f(x) = y,如果任意 x 属于 Z,且 y 也属于 Z,那么 Z 就对 f 是封闭的。

当然我们可以很容易地想到高中数学里面的列表。这跟 LISP 中的列表是完全对应的。正是这种特性造就了 LISP 语言的强大。但是这种模式对于即使不熟悉数学的程序员来说也应该似曾相识。比如 JUnit4 和 JMock 里面用的 Hamcrest Matcher。你可以任意组合各种 matcher 达到想要的效果。比如 assertThat(result, is(not(greaterThan(10)))。它使得 JUnit 摆脱了不停地往 Assert 类里面增加方法的局面。也是为什么 JUnit4 要绑定 Hamcrest Matcher 发布的原因。如今你很难看到一个优秀的测试框架里面不用 Hamcrest Matcher 的。Matcher 的模式就是:makeMatcher(someMather) === AnotherMatcher。也就是说,从逻辑上,makeMatcher 和 Matcher 这个抽象集合组成了一个代数空间。

找到这样的空间,我们就可能找到了非常强大而优雅的工具。比如 SICP 里面提到的 painter。我们可以生成一个给定 painter 的水平镜像 painter、垂直镜像 painter、扭曲 painter,等等。这点对于我们做面向对象设计的时候也极有启发价值。想想 Hamcreset Matcher……