summaryrefslogtreecommitdiff
path: root/doc/play/peano.go
diff options
context:
space:
mode:
Diffstat (limited to 'doc/play/peano.go')
-rw-r--r--doc/play/peano.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/doc/play/peano.go b/doc/play/peano.go
new file mode 100644
index 000000000..c1ee5ad45
--- /dev/null
+++ b/doc/play/peano.go
@@ -0,0 +1,88 @@
+// Peano integers are represented by a linked
+// list whose nodes contain no data
+// (the nodes are the data).
+// http://en.wikipedia.org/wiki/Peano_axioms
+
+// This program demonstrates the power of Go's
+// segmented stacks when doing massively
+// recursive computations.
+
+package main
+
+import "fmt"
+
+// Number is a pointer to a Number
+type Number *Number
+
+// The arithmetic value of a Number is the
+// count of the nodes comprising the list.
+// (See the count function below.)
+
+// -------------------------------------
+// Peano primitives
+
+func zero() *Number {
+ return nil
+}
+
+func isZero(x *Number) bool {
+ return x == nil
+}
+
+func add1(x *Number) *Number {
+ e := new(Number)
+ *e = x
+ return e
+}
+
+func sub1(x *Number) *Number {
+ return *x
+}
+
+func add(x, y *Number) *Number {
+ if isZero(y) {
+ return x
+ }
+ return add(add1(x), sub1(y))
+}
+
+func mul(x, y *Number) *Number {
+ if isZero(x) || isZero(y) {
+ return zero()
+ }
+ return add(mul(x, sub1(y)), x)
+}
+
+func fact(n *Number) *Number {
+ if isZero(n) {
+ return add1(zero())
+ }
+ return mul(fact(sub1(n)), n)
+}
+
+// -------------------------------------
+// Helpers to generate/count Peano integers
+
+func gen(n int) *Number {
+ if n > 0 {
+ return add1(gen(n - 1))
+ }
+ return zero()
+}
+
+func count(x *Number) int {
+ if isZero(x) {
+ return 0
+ }
+ return count(sub1(x)) + 1
+}
+
+// -------------------------------------
+// Print i! for i in [0,9]
+
+func main() {
+ for i := 0; i <= 9; i++ {
+ f := count(fact(gen(i)))
+ fmt.Println(i, "! =", f)
+ }
+}