MoMonkey 的个人资料Monkey Coder日志列表网络 工具 帮助

日志


8月19日

HOF + Purity = Concurrency

I had fun giving a talk Monday evening at the Spokane .NET User Group. Here's the deck if you're interested.
4月30日

Turtle Soup

I've been reading Seymour Papert's  Mindstorms book about Logo; very interesting! I'm just dying to add Turtle Graphics to my little toy language from last post (BTW, a friend suggested I call it "Ape" and I think I will!).

Logo with a twist

What I wanted was essentially Logo but not exactly. The "turtle" starts in the center of the canvas facing up (North). It can be instructed to turn "right" or "left" or to move "forward" or "back". It can also be asked to draw a "line" to its current position.

I didn't want to have some arbitrary distance for movement (turtle steps) or an arbitrary number of degrees for turning. Instead I did something a little strange :-) Everything is based on a unit circle in the center of the canvas. Moving "forward" will traverse the radius. Each move though divides the distance in half. So, for example, moving "forward back back back" will move from the center to the edge of the canvas, then "back" half of that (halfway between the center and the edge), "back" again will move another quarter, then an eighth. The net result is the same as moving forward an eighth of the radius. The same is true for turning "left" and "right". The first turn does a 180 (or a pi if you think in radians). The second makes a quarter turn, then an eighth, etc. So something like "right left left" is the same as turning clockwise 45 degrees. The move/turn deltas reset whenever a non-move/turn instruction is executed. Additionally, you can "stop" to reset. Also, you can return to "home" position (center facing up) any time. Sheesh, this is more difficult to explain in English than to just write the code already!

30-line Implementation

I didn't want to add new primitives to the language. If you read the last post, you know I quite like having boiled the language down to it's essence with just four primitives. Instead, think of Turtle Graphics as an output format. Rather than just printing a resulting symbol tree to the console, we paint a sequence of "turtle instructions." The AST passed in is not a tree. It's just a single flat list of Symbols.

open System.Drawing
open System.Windows.Forms
 
let draw turtle =
  let span = 200.
  let paint turtle (g : Graphics) =
    g.SmoothingMode <- Drawing2D.SmoothingMode.HighQuality
    g.Clear(Color.White)
    let line (x1, y1) (x2, y2) =
      let trans p = float32 (p * span + span)
      g.DrawLine(Pens.Black, trans x1, trans y1, trans x2, trans y2)
    let move (x, y) delta heading =
      let h = heading * 2. * Math.PI
      let dx = delta * sin h
      let dy = delta * cos h
      (x + dx, y + dy)
    let rec paint' turtle p1 p2 head dmove dturn =
      match turtle with
      | Symbol("right")  ::t-> paint' t p1 p2 (head - dturn) 1. (dturn/2.)
      | Symbol("left")   ::t-> paint' t p1 p2 (head + dturn) 1. (dturn/2.)
      | Symbol("forward")::t-> paint' t p1 (move p2 +dmove head) head (dmove/2.) 0.5
      | Symbol("back")   ::t-> paint' t p1 (move p2 -dmove head) head (dmove/2.) 0.5
      | Symbol("line")   ::t-> line p1 p2; paint' t p2 p2 head 1. 0.5
      | Symbol("stop")   ::t-> paint' t p1 p2 head 1. 0.5
      | Symbol("home")   ::t-> paint' t (0., 0.) (0., 0.) 0.5 1. 0.5
      | [] -> ()
      | invalid -> failwith "Invalid graphics output!"
    paint' (List.rev turtle) (0., 0.) (0., 0.) 0.5 1. 0.5
  let size = int (span * 2.)
  let form = new Form(Text       = "Turtle Graphics",
                      ClientSize = new Size(size, size),
                      Visible    = true)
  form.Paint.Add(fun a -> paint turtle a.Graphics)
  Application.Run(form) 

 

Take the Turtle for a Spin

We can now execute simple Ape programs and feed the output to this little rendering engine. For example:

forward back line right left left forward back line

image

Cool! That's not even really an Ape program; just a list of symbols being pushed through as literals. But we can refactor a bit into [forward back line] foo let foo right left left foo which does the same thing.

Prelude

Before we really get started, let's build up a little bit of "library" support. We have yet to add numbers to Ape, but we'll need a way of at least repeating operations some number of times:

[f let f f] 2 let
[f let f f f] 3 let
[f let f f f f] 4 let
...
[f let f f f f f f f f f f f f f f f] 15 let
[f let f f f f f f f f f f f f f f f f] 16 let

Silly but it works! Almost like a "tally mark" counting system, each of these will take a quoted expression and apply it n times.

I didn't want to bake in arbitrary movement and turning increments, but it is convenient to at least define some (but within Ape, not within the engine):

[forward back 4 stop] F let
[right left 4 stop]   R let
[left right 4 stop]   L let

Then from these define some common angles:

[[R] 8]   R90 let
[[R] 4]   R45 let
[[L] 8]   L90 let
[[L] 4]   L45 let

Interestingly, a series of "left right left right ..." will converge at 60 degrees, so an approximation:

[[right left] 16] R60 let
[[left right] 16] L60 let

And we can compose these to get other angles:

[R90 L60] R30 let
[L90 R60] L30 let

Shape Up!

Now that we have a bit of a foundation, it starts getting fun!

[[[F] 8 line R90] 4] square   let
[[[F] 8 line R60] 3] triangle let
[[F line R] 8]       arc      let
[[arc] 4]            circle   let

image  image  image

We can compose these:

[R90 square L90 L30 triangle] house let
house

image

We can start doing some powerful things; define procedures taking shapes and do things with them. Here, we draw a shape 16 times while rotating a bit each time:

[shape let [shape [R] 2] 16] pattern let

The results are very cool:

[square] pattern
[triangle] pattern
[circle] pattern

image  image  image

It's just so fun to play with!

[[arc R90] 2] peddle let
[[peddle R90] 4] flower let
[F] 6 [flower R45] 2 R90 [F] 12 line R90 peddle L90 [F] 6 line

image

Now remember that this is just 30 lines of code for the graphics rendering engine, 50 lines for the Ape interpreter, and another 30 lines for the lexer and parser. Pretty darn cool!

4月24日

Birth of a New Toy Language

I read “Thinking Fourth” and also played with Joy and Cat some time ago, but honestly I had written them off as “toy” languages. Recently I’ve had renewed interest in concatenative languages after watching Slava Pestov’s nice TechTalk about Factor. This is a very powerful implementation!

Variation

I decided to play with my own variation. The one thing that these stack-based languages seem to have in common is a soup of stack manipulation primitives and a lack of scoped name binding. They have a top-level “define” as their single means of abstraction. I understand the whole point-free style of concatenative languages in general, in which parameters are not named. I like this style actually because it is so very much more succinct! However, I don’t like the lack of scoped “defines” and I think that optionally popping and naming things on the stack can lead to clearer code in some cases. Also, I found that some of the other stack manipulation primitives were not really so “primitive.” If I had “let”, I could implement them in terms of it.

Barebones

What I really set out to do was to see what the minimal set of primitives should be. I found it annoying that Joy and Cat had all these stack manipulation primitives such as “dip”, “dup”, “pop”, “swap”, etc. My little moment of eureka was when I realized I could add a “let” primitive and get my scoped binding as well as be able to get rid of these other primitives!

The language and data structure revolves around an extremely simplified AST structure:

type node = Symbol of string

          | List of node list

We have atomic Symbols and composite Lists (of Symbols and/or other Lists). That’s it! There is no native concept of Integers, Booleans, etc.  Only Symbols. Further, there are only four primitive operations in my new language!

cons/uncons

We need a means of composing and decomposing structures. This is done through cons (adding a given node to a List) and uncons (breaking a given List into it’s “head” node and “tail” remaining List). For example:

a []      cons yields [a]
a [b c]   cons yields [a b c]
[a] [b c] cons
yields [[a] b c]

Decomposition yields the opposite:

[a]       uncons yields a []
[a b c]   uncons
yields a [b c]
[[a] b c] uncons
yields [a] [b c]

eq

For Symbols to be of any use at all, we need at least one operation we can perform on them. The single operation in the language is eq which compares two Symbols (or Lists) and evaluates one or another expression as a result. It takes four arguments, compares the first two and evaluates the third or fourth. For example:

foo foo [yes] [no] eq yields yes
foo bar [yes] [no] eq
yields no

The equality comparison walks the complete structure in the case of Lists. For example:

[foo bar [baz]] [foo bar [baz]] [yes] [no] eq yields yes

let

The final missing piece is a means of abstraction. This is the most fundamental part of any useful language. We need to be able to introduce new “words” to the language and then use them as if they were primitives. For this, we have let.

Let can be used to define new primitives by assigning a name to a List. For example, we could define a new “triple cons” operation such as:

[cons cons cons] tcons let

And now can, for example, use our new “word” to cons three Symbols onto an empty list:

a b c [] tcons yields [a b c]

Neat!

We do have to have slightly special semantics for let. It does not apply to the top stack node as most “words” do. To ensure that Symbols used as identifiers are not evaluated, we do a single ‘look ahead’ while interpreting the code specifically require that the pattern a let means “bind the top stack node to the Symbol a.”

Crazy-tiny Interpreter

The interpreter is ridiculously small; less than 50 lines of code!

let interpret input ast =

  let rec interpret' ast stack env =

    match ast with

    | Symbol(n) :: Symbol("let") :: tl ->

      match stack with

      | x :: s -> interpret' tl s (Map.add n x env)

      | _ -> failwith "Invalid stack state for 'let'."

    | Symbol(x) :: tl ->

      match Map.tryfind x env with

      | Some(List(f)) ->

        let r = match f with

                | [Symbol(y)] ->

                  if y = x then (Symbol(y) :: stack)

                  else interpret' f stack env

                | _ -> interpret' f stack env

        interpret' tl r env

      | Some(m) ->

        interpret' tl (m :: stack) env

      | None ->

        match x with

        | "cons" ->

          match stack with

          | List(t) :: h :: s -> interpret' tl (List(h :: t) :: s) env

          | _ -> failwith "Invalid stack state for 'cons'."

        | "uncons" ->

          match stack with

          | List(h :: t) :: s -> interpret' tl (h :: List(t) :: s) env

          | _ -> failwith "Invalid stack state for 'uncons'"

        | "let" -> failwith "Malformed 'let'."

        | "eq" ->

          match stack with

          | n :: y :: a :: b :: s ->

            let yn = if a = b then y else n

            match yn with

            | List(yn) ->

              let r = interpret' yn s env

              interpret' tl r env

            | _ -> interpret' tl (yn :: s) env

          | _ -> failwith "Not enough args on the stack!"

        | _ -> interpret' tl (Symbol(x) :: stack) env

    | x :: tl ->

      interpret' tl (x :: stack) env

    | [] -> stack

  interpret' ast input Map.empty

Of course, if you want to use it you’ll also want a lexer and parser to convert source code to a node tree:

type token = WhiteSpace

           | CombinationStart

           | CombinationEnd

           | Word of string

 

let lexer source =

  let rec lexer' source token result =

    let emit t tail =

      if List.length token > 0

      then lexer' tail [] (t :: Word(new string(List.to_array (List.rev token))) :: result)

      else lexer' tail [] (t :: result)

    match source with

    | w :: t when (Char.IsWhiteSpace(w)) -> emit WhiteSpace t

    | '[' :: t -> emit CombinationEnd t

    | ']' :: t -> emit CombinationStart t

    | h :: t -> lexer' t (h :: token) result

    | [] -> result

  lexer' ((List.of_seq source) @ [' ']) [] []

 

let parser tokens =

  let rec parser' tokens result =

    match tokens with

    | Word(s) :: t ->

      symbolCount := symbolCount.Value + 1

      parser' t (Symbol(s) :: result)

    | CombinationStart :: t ->

      listCount := listCount.Value + 1

      let n, t = parser' t []

      parser' t (n :: result)

    | CombinationEnd :: t -> List(result), t

    | WhiteSpace :: t -> parser' t result

    | [] -> List(result), []

  let result, _ = parser' tokens []

  result

And you may want a way of “pretty printing” the program output:

let output ast =

  let rec output' ast result =

    match ast with

    | Symbol(s) :: tl -> output' tl (result + " " + s)

    | List(l) :: tl -> output' tl (result + " [" + (output' l "") + " ]")

    | [] -> result

  output' ast ""

First “Joy”ful Steps

Now back to the so-called primitives who’s existence I found annoying in Joy and Cat. These can now be implemented in terms of the core four (cons, uncons, eq, let):

[x let]                             pop   let // throw away top stack node
[a let a]                           apply let // evaluate top stack List
[[] cons]                           quote let
// wrap top stack node into a List
[quote a let a a]                   dup   let // duplicate top stack node
[quote a let quote b let a apply b] dip   let // apply 2nd stack node
[quote a let quote e let a e]       swap  let // apply 2nd stack node

 

I like this much better than adding them to the core language!

You may have also noticed that the standard Lisp-esque car and cdr (or Haskell-esque head and tail) are missing from the language. They can be defined in terms of uncons:

[uncons swap pop] head let

[uncons pop]      tail let

Boolean Logic

There is no Boolean type in the language. There is not even an if word! Let’s implement them!

Using the symbols #t and #f to mean True and False (in Scheme-esque fashion), we can implement if in terms of eq:

[[#t swap] dip eq] if let

And we can start implementing the standard Boolean logic operators (not, and, or, xor) in terms of this:

[#f #t if]                  not? let

[[] [pop #f] if]            and? let

[[pop #t] [#t #t #f eq] if] or?  let

[#t [not?] [] eq]           xor? let

Also useful will be to create function that check equality to well known values and return #t or #f for use with other Boolean operators:

[#t #f eq]  equal? let

[[] equal?] empty? let

[0 equal?]  zero?  let

[]          true?  let // wow, easy!

[not?]      false? Let

What now?

Well, now I’m going to add higher-order functions such as map, filter, fold, … and then add some basic arithmetic (using lists of decimal digits to represent numbers).

Wow, a language with just Symbols and Lists for structure, just four operators and a 50-line interpreter. How fun! Is it just a “toy”? I’ll see how far I can take it… lots of ideas!

7月17日

Rubik's Cube Solver

A while back, I had some fun making a Rubik's cube solver in F#. I was planning to make a "pluggable algorithm" mechanism so that I could have it solve using other human-style systems such as Petrus, Fridrich, etc., but right now it just uses a vanilla layer-by-layer system. I've lost interest in this hobby-project so now just posting as is:
 
The UI
 
The UI is a bit ugly (nice 3D cube would be good) but works. It's an "unfolded" projection of the cube faces:
 
Reset
You can flip the left, right, up, down, front, and back faces by pressing L, R, U, D, F or B keys respectively and you can rotate the whole cube on it's X, Y or Z axis with those keys or with the arrow keys (X/Y axis only). You can also mix it up with M and reset it with Spacebar.
For example, U R D L produces:
URDL
Or, from the reset position, U U D D L L R R F F B B produces the nice pattern:
UUDDLLRRFFBB
The real purpose though was to make a solver. Each time you press S, it manipulates the cube a step closer to being solved. The interesting thing (to my anyway) is that the solving algorithm is a single function that takes a single argument of a cube in a particular state and returns a new cube that's been manipulated a bit. The process of solving is just to iterate this function. The only state in the system is the state of the cube being displayed; literally you will see in the code that there is a single cube ref and no other mutables at all.
 
The Code
 
The Cube is represented as a 3x3x3 array of Cublets, each of which have an up/down/left/right/front/back Sticker:
 
#light
 
open System.Drawing
open System.Windows.Forms
 
type Sticker = Red | Orange | Yellow | Green | Blue | White
 
Cublets just have the six stickers and methods for manipulating their orientation:
 
// The naming conventions for all the transforms (e.g X,
// X2, X', Y, Z, F, U, D, D', L2, etc.)
// come from http://www.cubewhiz.com/notation.html
 
type Cublet = class
    val up    : Sticker; val down  : Sticker
    val left  : Sticker; val right : Sticker
    val front : Sticker; val back  : Sticker
    new(u, d, l, r, f, b) = { up = u; down = d; left = l; right = r; front = f; back = b }
    new() = { up    = Sticker.Red;    down  = Sticker.Orange;
              left  = Sticker.Yellow; right = Sticker.White;
              front = Sticker.Blue;   back  = Sticker.Green }
    member c.X  = new Cublet(c.front, c.back, c.left, c.right, c.down, c.up) // back on X-axis
    member c.X2 = c.X.X // 180 on X-axis
    member c.X' = c.X2.X // inverse - forward on X-axis (same as back 3)
    member c.Y  = new Cublet(c.up, c.down, c.front, c.back, c.right, c.left) // left on Y-axis
    member c.Y2 = c.Y.Y // 180 on Y-axis
    member c.Y' = c.Y2.Y // inverse - right on Y-axis (same as left 3)
    member c.Z  = c.X.Y.X' // clockwise on Z-axis (same as X, Y, X')
    member c.Z2 = c.Z.Z // 180 on Z-axis
    member c.Z' = c.Z2.Z // inverse - counter clockwise on Z-axis (same as clockwise 3)
end
 
Finally, the Cube is a 3x3x3 array of Cublets with methods for manipulating sets of them (rotating slices or changing orientation of the whole cube):
 
let s = 3 // Cube dimentions
let a = Array3.init s s s
 
type Cube = class
    val cublets : Cublet [,,]
    new(c) = { cublets = c }
    new() = { cublets = a (fun _ _ _ -> new Cublet()) }
    member c.X = new Cube(a (fun x y z -> c.cublets.[x, s - z - 1, y].X)) // back on X-axis
    member c.X2 = c.X.X // 180 on X-axis
    member c.X' = c.X.X.X // inverse - forward on X-axis (same as back 3)
    member c.Y = new Cube(a (fun x y z -> c.cublets.[s - z - 1, y, x].Y)) // left on Y-axis
    member c.Y2 = c.Y.Y // 180 on Y-axis
    member c.Y' = c.Y2.Y // inverse - right on Y-axis (same as left 3)
    member c.Z  = c.X.Y.X' // clockwise on Z-axis (same as X, Y, X')
    member c.Z2 = c.Z.Z // 180 on Z-axis
    member c.Z' = c.Z2.Z // inverse - counter clockwise on Z-axis (same as clockwise 3)
    member c.F = new Cube(a (fun x y z -> if z = 0 then c.cublets.[y, s - x - 1, z].Z else c.cublets.[x, y, z]) )
    member c.F2 = c.F.F
    member c.F' = c.F2.F
    member c.B = c.Y2.F.Y2 // everything defined in terms of F, X and Y!
    member c.B2 = c.B.B
    member c.B' = c.B2.B
    member c.L = c.Y'.F.Y
    member c.L2 = c.L.L
    member c.L' = c.L2.L
    member c.R = c.Y.F.Y'
    member c.R2 = c.R.R
    member c.R' = c.R2.R
    member c.U = c.X'.F.X
    member c.U2 = c.U.U
    member c.U' = c.U2.U
    member c.D = c.X.F.X'
    member c.D2 = c.D.D
    member c.D' = c.D2.D
end 
 
The solver is a giant beast! The cool thing about it is that you just give it a Cube (in any state) and it gives you one back, having done some manipulations. It reports to the console what it's "thinking" as it goes.
Here's a sample solve (showing completion of each phase; it actually took ~80 steps pressing 'S' key):
 
Mixed  Mixed
Phase1 Phase 1 - White cross
Phase2 Phase 2 - Bottom layer corners
Phase3 Phase 3 - Middle layer edges
Phase4 Phase 4 - Yellow cross on top
Phase5 Phase 5 - Yellow top complete
Phase6 Phase 6 - Top corners aligned
Solved  Solved!
Report
 
The code is one giant "solve" function:
 
[Dang it! Silly MSN Spaces won't let me paste so much in with color highlighting... Confused]
 
let solve (c : Cube) =
    let furc = c.cublets.[2, 0, 0].front
    let ufrc = c.cublets.[2, 0, 0].up
    let rufc = c.cublets.[2, 0, 0].right
    let fdrc = c.cublets.[2, 2, 0].front
    let dfrc = c.cublets.[2, 2, 0].down
    let rdfc = c.cublets.[2, 2, 0].right
    let dfe = c.cublets.[1, 2, 0].down
    let fde = c.cublets.[1, 2, 0].front
    let dbe = c.cublets.[1, 2, 2].down
    let dre = c.cublets.[2, 2, 1].down
    let bde = c.cublets.[1, 2, 2].back
    let dle = c.cublets.[0, 2, 1].down
    let ule = c.cublets.[0, 0, 1].up
    let ure = c.cublets.[2, 0, 1].up
    let ufe = c.cublets.[1, 0, 0].up
    let ube = c.cublets.[1, 0, 2].up
    let ublc = c.cublets.[0, 0, 2].up
    let ubrc = c.cublets.[2, 0, 2].up
    let uflc = c.cublets.[0, 0, 0].up
    let ufrc = c.cublets.[2, 0, 0].up
    let bulc = c.cublets.[0, 0, 2].back
    let burc = c.cublets.[2, 0, 2].back
    let lubc = c.cublets.[0, 0, 2].left
    let lufc = c.cublets.[0, 0, 0].left
    let fulc = c.cublets.[0, 0, 0].front
    let furc = c.cublets.[2, 0, 0].front
    let rubc = c.cublets.[2, 0, 2].right
    let rufc = c.cublets.[2, 0, 0].right
    let fue = c.cublets.[1, 0, 0].front
    let lue = c.cublets.[0, 0, 1].left
    let rue = c.cublets.[2, 0, 1].right
    let bue = c.cublets.[1, 0, 2].back
    let fs = c.cublets.[1, 1, 0].front
    let bs = c.cublets.[1, 1, 2].back
    let ls = c.cublets.[0, 1, 1].left
    let rs = c.cublets.[2, 1, 1].right
    let w = Sticker.White
    let y = Sticker.Yellow
    let fre_done (c : Cube) =
        c.cublets.[2, 1, 0].front = c.cublets.[1, 1, 0].front &&
        c.cublets.[2, 1, 0].right = c.cublets.[2, 1, 1].right
    printfn "------------------------------------------------------------"
    match c.cublets.[1, 0, 1].up (* up center *), c.cublets.[1, 1, 0].front (*front center *) with
    | Sticker.Yellow, _ -> // top already yellow
        printfn "Phase 0: Top is yellow."
        if // white cross on down-side complete?
            dfe = w && fde = fs && dbe = w && bde = bs && dle = w && bde = bs && dre = w
        then
            printfn "Phase 1: White cross is complete.";
            let frdc_done (c : Cube) =
                c.cublets.[2, 2, 0].down = w &&
                c.cublets.[2, 2, 0].front = c.cublets.[1, 1, 0].front &&
                c.cublets.[2, 2, 0].right = c.cublets.[2, 1, 1].right
            if frdc_done c && frdc_done c.Y && frdc_done c.Y2 && frdc_done c.Y' // corners complete?
            then
                printfn "Phase 2: Bottom layer corners are complete.";
                if fre_done c && fre_done c.Y && fre_done c.Y2 && fre_done c.Y'
                then
                    printfn "Phase 3: Middle layer edges in place."
                    if ule = y && ure = y && ufe = y && ube = y // yellow cross?
                    then
                        printfn "Phase 4: Yellow cross on top complete."
                        let n = Array.sumByInt (fun c -> if c = y then 1 else 0) [| uflc; ufrc; ublc; ubrc |]
                        if n = 4 then
                            printfn "Phase 5: Yellow top face complete."
                            let bp = bulc = burc
                            let lp = lubc = lufc
                            let fp = fulc = furc
                            let rp = rubc = rufc
                            if bp && lp && fp && rp
                            then
                                printfn "Phase 6: Top corners aligned."
                                if lue = ls && bue = bs && rue = rs && fue = fs // solved?!
                                then printfn "Phase 7: SOLVED!"; c
                                elif lue = lubc then printfn "  Move finished edge from left to the back."; c.U
                                elif rue = rubc then printfn "  Move finished edge from right to the back."; c.U'
                                elif fue = fulc then printfn "  Move finished edge from front to the back."; c.U2
                                elif fue = rubc then printfn "  Move front edge (right) into place."; c.F2.U'.L.R'.F2.L'.R.U'.F2.U2
                                elif fue = lubc then printfn "  Move front edge (left) into place."; c.F2.U.L.R'.F2.L'.R.U.F2.U2
                                else c
                            elif lp then printfn "  Move paired corners from left to the back."; c.Y
                            elif rp then printfn "  Move paired corners from right to the back."; c.Y'
                            elif lp then printfn "  Move paired corners from front to the back."; c.Y2
                            else printfn "  Permutate top corners."; c.R'.F.R'.B2.R.F'.R'.B2.R2
                        else
                            // get top yellow face
                            if
                                if n = 0 then
                                    printfn "  No yellow corners on top."
                                    c.cublets.[0, 0, 0].left = y
                                elif n = 1 then
                                    printfn "  1 yellow corners on top."
                                    c.cublets.[0, 0, 0].up = y
                                elif n = 2 then
                                    printfn "  2 yellow corners on top."
                                    c.cublets.[0, 0, 0].front = y
                                else failwith "Impossible position!"
                            then printfn "  Permutate yellow corders."; c.R.U.R'.U.R.U2.R'
                            else printfn "  Rotate yellow corner into position according to corner count."; c.U
                    // get yellow cross
                    elif ule <> y && (ure = y || ufe = y || ube = y)
                    then printfn "  Line up top yellow pattern."; c.U
                    else printfn "  Permutate yellow edges."; c.F.U.R.U'.R'.F'.U
                else
                    // get middle layer edges in place
                    if fre_done c
                    then printfn "  Middle layer edge in place. Next..."; c.Y
                    elif c.cublets.[2, 1, 0].front = rs && c.cublets.[2, 1, 0].right = fs
                    then printfn "  Middle layer edge in place, but flipped wrong."; c.R.U.R'.U'.F'.U'.F.U'.R.U.R'.U'.F'.U'.F
                    elif c.cublets.[2, 0, 0].front = fs && c.cublets.[2, 0, 0].up <> y
                    then printfn "  Middle layer edge just nearly in place."; c.U // it will go in next most
                    else printfn "  Permutate top and right front edges."; c.R.U.R'.U'.F'.U'.F.U.Y
            else
                // get bottom corners in
                if // corner in place?
                    dfrc = w && fdrc = fs && rdfc = rs
                then printfn " Down-right corner already in place. Rotate view."; c.Y
                elif // corner at least lined up vertically?
                    ( // furc lined up?
                        (furc = w || ufrc = w || rufc = w) && // white?
                        (furc = fs || ufrc = fs || rufc = fs) && (furc = rs || ufrc = rs || rufc = rs) // correct corner?
                    ) ||
                    ( // fdrc lined up?
                        (fdrc = w || dfrc = w || rdfc = w) && // white?
                        (fdrc = fs || dfrc = fs || rdfc = fs) && (fdrc = rs || dfrc = rs || rdfc = rs) // correct corner?
                    )
                then printfn "  Slip white corner into place."; c.R.U.R'.U'
                else printfn "  Safely permutate corners."; c.U2.R.U.R'.U'.Y
        // line up white edges to make cross on down-side
        elif // white edge lined up with correct right-center?
            c.cublets.[2, 1, 0].front (* front right edge *) = w &&
            c.cublets.[2, 1, 0].right (* right front edge *) = rs
        then printfn "  Rotate right white edge in."; c.R' // rotate white edge in
        elif // white edge lined up with correct right-center, but flipped wrong way?
            c.cublets.[2, 1, 0].front (* front right edge *) = rs &&
            c.cublets.[2, 1, 0].right (* right front edge *) = w
        then printfn "  Rotate flipped right white edge in."; c.D'.F.D // rotate white edge in
        elif // white edge lined up with correct down-center, but flipped wrong way?
            c.cublets.[2, 2, 1].right (* right down edge *) = w &&
            c.cublets.[2, 2, 1].down (* down right edge *) = rs
        then printfn "  Rotate flipped down white edge in."; c.R.D'.F.D // rotate white edge in
        elif // white edge on down side, but wrong one?
            c.cublets.[2, 2, 1].down (* right down edge *) = w &&
            c.cublets.[2, 2, 1].right (* down right edge *) <> rs // wrong color?
        then printfn "  Rotate wrong down white edge to top."; c.R2.U // rotate white edge out
        else printfn "  Safely permutate edges."; c.R.U.R'.U'.Y // just safely "stir thing up" and continue
    // look at two faces and flip yellow to up
    | _,              Sticker.Yellow -> printfn "  Flip yellow side from front to up."; c.X  // front is yellow
    | _,              Sticker.White  -> printfn "  Flip yellow side from back to up."; c.X' // back must be yellow
    | Sticker.White,  _              -> printfn "  Flip yellow side from down to up."; c.X2 // down must be yellow
    | Sticker.Red,    Sticker.Blue
    | Sticker.Blue,   Sticker.Orange
    | Sticker.Orange, Sticker.Green
    | Sticker.Green,  Sticker.Red
        -> printfn "  Flip yellow side from left to up."; c.Z  // left must be yellow
    | Sticker.Blue,   Sticker.Red
    | Sticker.Red,    Sticker.Green
    | Sticker.Green,  Sticker.Orange
    | Sticker.Orange, Sticker.Blue
        -> printfn "  Flip yellow side from right to up."; c.Z'  // right must be yellow
    | _ -> failwith "Impossible position!"
 
So, finally the UI is very simple; just painting and key wireup:
let form =
    let c = ref (new Cube())
    let key_mapping k s =
        match k with
            | Keys.Left  -> (!c).Y'
            | Keys.Right -> (!c).Y
            | Keys.Up    -> (!c).X
            | Keys.Down  -> (!c).X'
            | Keys.X     -> if s then (!c).X' else (!c).X
            | Keys.Y     -> if s then (!c).Y' else (!c).Y
            | Keys.Z     -> if s then (!c).Z' else (!c).Z
            | Keys.F     -> if s then (!c).F' else (!c).F
            | Keys.B     -> if s then (!c).B' else (!c).B
            | Keys.L     -> if s then (!c).L' else (!c).L
            | Keys.R     -> if s then (!c).R' else (!c).R
            | Keys.U     -> if s then (!c).U' else (!c).U
            | Keys.D     -> if s then (!c).D' else (!c).D
            | Keys.S     -> solve (!c)
            | Keys.P     -> (!c).U.R2.F.B.R.B2.R.U2.L.B2.R.U'.D'.R2.F.R'.L.B2.U2.F2 // so called "super-flip"
            | Keys.M     -> (!c).B.U2.B2.U.R.U2.R'.D'.U.F.L.F2.R.L.D.R2.U'.B'.F2.L'.B2.R2.U2.L2.B
            | Keys.Space -> (new Cube()) // reset
            | _          -> !c // no change
    let face_to_color =
        let brush r g b = new SolidBrush(Color.FromArgb(r, g, b))
        function // "official" Rubik's cube colors
        | Sticker.Red    -> brush 0xcc 0x00 0x00
        | Sticker.Orange -> brush 0xff 0x66 0x00
        | Sticker.Yellow -> brush 0xff 0xff 0x00
        | Sticker.Green  -> brush 0x00 0x99 0x00
        | Sticker.Blue   -> brush 0x00 0x00 0xdd
        | Sticker.White  -> brush 0xff 0xff 0xff
    let paintFace (s : int) (g : Graphics) x y f =
        g.FillRectangle(face_to_color f, x, y, s, s)
        g.DrawRectangle(Pens.Black, x, y, s, s)
    let paintCube (w : int) h =
        let b = new Bitmap(w, h)
        use g = Graphics.FromImage(b)
        g.Clear(Color.Gray)
        let s = Array3.length1 (!c).cublets // assumes cubic
        let q = 40 // cublet size
        let ox = 150 // origin
        let oy = 150 // origin
        let p = 6 // padding
        let f = q * 3 + p
        let pf = paintFace q g  // partially applied
        for i = 0 to s - 1 do
            for j = 0 to s - 1 do
                let x = i * q + ox
                let y = j * q + oy
                let ii = s - i - 1
                let jj = s - j - 1
                pf  x           y       (!c).cublets.[i,  j, 0 ].front
                pf (x - f)      y       (!c).cublets.[0,  j, ii].left
                pf (x + f)      y       (!c).cublets.[2,  j, i ].right
                pf (x + f * 2)  y       (!c).cublets.[ii, j, 2 ].back
                pf x           (y - f)  (!c).cublets.[i,  0, jj].up
                pf x           (y + f)  (!c).cublets.[i,  2, j ].down
        b
    let f = new Form(
                     Text = "Rubik's Cube",
                     Width  = 570,
                     Height = 450,
                     Visible = true)
    f.Paint.Add(fun a -> a.Graphics.DrawImage(paintCube f.Width f.Height, 0, 0))
    f.KeyDown.Add(fun a -> c := key_mapping a.KeyCode a.Shift; f.Refresh())
    f
Application.Run(form)
Looks like a lot of work but really less than 300 lines of code; Fun little toy project!
5月2日

Closures to the Rescue

A coworker just walked into my office with an interesting refactoring question; hoping an FP-style would help. I think it’s a decent example of how mutation generally gets in the way of compositionality, but also of how FP can still be applied in a mixed world like this; a good enough example, I thought I’d blog about it.

Basically he has a standard “hole in the middle” problem for which FP is normally perfect, but in his case the code is written in an imperative style and so the “holes” have to share state. Essentially, he has some retry logic that he wants to reuse. The “holes” are to A) initialize some state, B) make multiple attempts to do something that may fail (e.g. network requests, etc.), and C) finish by cleaning up and generating a result of some kind.

Example

First we need something dangerous to try (and retry upon failure). For simplicity, I’ll just use a silly DiceRoll() function that blows up 1/7th of the time:

    private static int DiceRoll()
    {
        // generates random number from 0-6 but throws if 0!
        // simulating some call with external influences that may cause
        // it to fail (e.g. network I/O, etc.)
        int r = new Random((int)DateTime.Now.Ticks % int.MaxValue).Next(6);
        if (r == 0)
            throw new Exception();
        return r;
    }

Then, a super-simplified version of some kind of retry logic; in this case returning the sqrt of 2 + a random dice roll (real useful stuff). It’ll give it three chances before giving up:

    // A) init (mutation!)
    int x = 2;
   
    int retry = 0; // attempt count
    while (true)
    {
        try
        {
            // B) attept to do something dangerous
            x += DiceRoll();
 
            break;
        }
        catch (Exception ex)
        {
            if (++retry >= 3) // (mutation!)
                throw ex; // give up...
        }
    }
 
    // C) finish with doing something with result
    Console.WriteLine(Math.Sqrt(x));

We’d like to reuse this logic; plugging in new implementations of the A, B and C “holes”. How do we do that? From an FP mindset, the first thing that comes to mind is to bundle it up as a function taking three higher-order functions (A, B and C) as arguments.

The Problem

In a pure functional world, that would be perfectly easy and you’d be free to compose any arbitrary (independent) implementations of A, B and C. The main problem here is that B depends on the state left behind by A (in this case, the value of ‘x’), and C depends on the state changes made by B; they’re not independent.

Shared state makes it messy (this is why FPers avoid it). By definition this gets in the way of composing “mis-matched” A/B/C sets, but it shouldn’t get in the way of generally passing in higher-order functions to factor out the reusable retry logic.

We just need some way to pass around separate functions that share state.

OO Solution

 The OO programmers first thought is to not make them entirely separate functions, but to make them separate methods of one object containing the shared state. We’d start out with an interface or abstract class:

    public interface IAttemptDangerousThings
    {
        void Init();
        void Attempt();
        void Finish();
    }

Then we’d implement the “holes”:

    public class AttemptMe : IAttemptDangerousThings
    {
        public void Init() { x = 2; }
        public void Attempt() { x += DiceRoll(); }
        public void Finish() { Console.WriteLine(Math.Sqrt(x)); }
        private int x; // mutable shared state!
    }

Finally, we’d make a function that bundles up the retry logic and takes instances of this interface type (or make it a member, but then it’s harder to mix and match with different ‘retry’ implementations).

    public static void OOSolution(IAttemptDangerousThings doSomething)
    {
        doSomething.Init(); // A) init (mutation!)
 
        int retry = 0; // attempt count
        while (true)
        {
            try
            {
                doSomething.Attempt(); // B) attept to do something dangerous
                break;
            }
            catch (Exception ex)
            {
                if (++retry >= 3) // (mutation!)
                    throw ex; // give up...
            }
        } 
 
        doSomething.Finish(); // C) finish with doing something with result
    }

We get the compositionality we wanted. We can even use inheritance to compose various versions of A, B and C (in limited ways).

FP Solution

The idea of refactoring the way we have so far is already an FP-type idea, but the main reason I dislike the OO “packaging” of higher-order functions with shared state is just that it’s verbose; having to construct whole class hierarchies just for “packaging” and also I think inheritance is a clunky way of allowing mixing and matching A’s, B’s, and C’s.

I’d much rather just use a delegate:

    public delegate void DoSomething();

And change the retry logic to take three of these guys:

    public static void FPSolution(
        DoSomething init,
        DoSomething attempt,
        DoSomething finish)
    {
        init(); // A) init
 
        int retry = 0; // attempt count
        while (true)
        {
            try
            {
                attempt(); // B) attept to do something dangerous
                break;
            }
            catch (Exception ex)
            {
                if (++retry >= 3) // (mutation!)
                    throw ex; // give up...
            }
        }
 
        finish(); // C) finish with doing something with result
    }
} 

Then it’s very simple and lightweight to throw together the pieces:

    int y = 0; // what the?! delegates can access this?
    var init = new DoSomething(delegate { y = 2; });
    var attempt = new DoSomething(delegate { y += DiceRoll(); });
    var finish = new DoSomething(delegate { Console.WriteLine(Math.Sqrt(y)); });

Closures!

What might look strange about the three anonymous delegates above is that they all refer to ‘y’, which is defined outside of their scope! If you haven’t seen this before you might be wondering if that really compiles, and what happens when the locals go out of scope but the delegates still exist on the heap. If you’ve always thought of delegates as just type safe function pointers, they’re more than that. They are ‘closures’ that can ‘capture’ the environment in which they’re first created. They can even be returned out of their original scope and continue to capture out-of-scope variable (such as ‘y’).

It’s pretty cool stuff! In fact, who even needs OO? Really, “objects” with private state and methods that share it can easily be simulated with closures. Plenty of OO systems with inheritance, polymorphism and the whole shebang have been built in Scheme this way. It’s an age-old thing in FP languages, but new in C# since anonymous delegates were introduced.

Anyway, now we can just pass these delegates/closures into our FPSolution(init, attempt, finish); and voila!

12月3日

The Lambda Calculus

Mads Torgersen's post the other day was very cool! The first time I really understood Lambda Calculus was from this little 8-page paper - for some reason, relating it to Scheme made it stick for me. After reading Dr. T's post I was just now having some fun playing with it in Scheme and couldn't resist making a post of my own Smile

To start off, we can define true, false and if:

(define (true a b) a)
(define (false a b) b)
(define (if c a b) (c a b)) ; doesn't do much besides adding familiar 'if' syntax

Each of 'true' and 'false' are functions taking a pair of arguments and return one or the other of them. Then 'if' simply takes a boolean (instance of our true/false function) and applies it to a pair. Very strange to think of 'true' and 'false' as functions but everything is a function in Lambda Calculus. We can test it out with:

> (if true 1 2)
1
> (if false 1 2)
2

Works! This is very similar to how 'cons', 'car' and 'cdr' are defined:

(define (cons a b) (lambda (c) (if c a b)))
(define (car c) (c true))
(define (cdr c) (c false))

Calling 'cons' creates a pair in the form of a closure that when passed 'true' returns the head and when passed 'false' returned the tail. Again, it's strange to think of a pair not as a data structure but as a function - everything is a function in LC. Seeing this was one of the awe moments for me when when going through SICP. So, the 'car', just takes a pair and calls it with 'true'. Likewise 'cdr' calls with 'false'. Simple as that. We can test it:

> (define foo (cons 1 2))
> (car foo)
1
> (cdr foo)
2

For demonstration, we're using the Scheme number literals '1' and '2' but these don't exist in LC! Instead, how do you get numbers? Did I mention that everything is a function in LC?! Yes, these too are functions:

(define (zero  f) (lambda (x) x))
(define (one   f) (lambda (x) (f x)))
(define (two   f) (lambda (x) (f (f x))))
(define (three f) (lambda (x) (f (f (f x)))))
...

What the heck?! In Church encoded numerals, 'one' is a function that takes a function as an argument and applies it once. Similarly, 'two' takes a function and applies it twice ("f of f of x"), 'three' applies three times, etc. Does your brain hurt yet? That's all part of the fun!

Once we start working with Church Numerals, we'll need a way to visualize them. Here's a helper to convert Church Numerals to normal Scheme Numerals:

(define (print n) ((n (lambda (n) (+ n 1))) 0))

It uses the fact that Church Numerals are functions that apply functions n times. (print n) will apply n to a simple "increment" function, producing a result we can see printed for human consumption. It uses the '+' operator and Scheme literals '0' and '1' which aren't part of LC - just for demo purposes. So now we can do things like:

> (print one)
1
> (print three)
3

Another useful function for dealing with Church numerals is to be able to recognize zero (from this we could build greater-than/less-than/equal-to operators):

(define (zero? n) ((n (lambda (x) false)) true))

This 'zero?' function works by the fact that the Church numeral 'zero' applies its argument (a function) zero times, so we pass a function that, if called at all, returns false. Funny, eh? We can try it out (along with our 'if'):

> (if (zero? three) "yes" "no")
"no"
> (if (zero? zero ) "yes" "no")
"yes"

It's a pain to define each of our 'one', 'two', 'three' literals. We can generalize the process with a 'succ' (successor) function:

(define (succ n) (lambda (f) (lambda (x) (f ((n f) x)))))

... and then redefine our natural number literals in terms each other - ultimately in terms of just 'zero' (like Peano's 5th and 6th postulates):

(define one   (succ zero))
(define two   (succ one))
(define three (succ two))
(define four  (succ three))
(define five  (succ four))
(define six   (succ five))
(define seven (succ six))
(define eight (succ seven))
(define nine  (succ eight))
(define ten   (succ nine))

Cool, now we can even generate numbers for which we have no literal defined:

> (print (succ ten))
11

Defining 'pred' (predecessor) is a little tricky:

(define (pred n) (cdr ((n (lambda (p) (cons (succ (car p)) (car p)))) (cons zero zero))))

We define a function that generates pairs of numbers (using our 'cons') which represent the next (using our 'succ') and the previous number. Given a pair, it will generate the next pair. So we can call it n times starting with (cons zero zero) and then take the 'cdr' and voila, we have the number prior to n. Of course, we call it n times by passing it to n (working with Church numerals is so weird!). It all works:

> (print (pred seven))
6

Using 'pred' we can define 'sub' (subtract) and we can define 'add' in terms of 'succ'. Then we can define 'mult' in terms of 'add'. In fact, there's nothing in mathematics that cannot be defined ultimately in LC!

(define (sub a b) ((b pred) a))
(define (add a b) ((b succ) a))
(define (mult a b) ((a (lambda (x) (add x b))) zero))

The most insane thing of all is when you get to the Y Combinator which finds the fixed point of other functions so that they can "generate themselves" to do recursion. Below is the Z Combinator (just like Y but made for applicative order languages like Scheme - where just the definition of Y would cause infinite evaluation!). I'm not going to try to explain it (the two links at the top of this post do a better job than I ever could):

(define Z (lambda (f) ((lambda (x) (f (lambda (y) ((x x) y)))) (lambda (x) (f (lambda (y) ((x x) y)))))))

Now, for the grand finale. We can define good ol' factorial as a function that takes an instance of itself (here 'f') and does the normal, "if n is zero then return 1, otherwise return n * factorial of n - 1" only when it says "factorial of ..." it means "apply the instance of ourselves that was passed in". Very strange stuff, but this essentially defines 'fac' in terms of itself without itself referring to the name 'fac' anywhere in it's body:

(define fac (Z (lambda (f) (lambda (n) (if (zero? n) one (mult n (f (sub n one))))))))

And finally, we can test this out:

> (print (fac seven))
5040

Amazing!

If we really want to get crazy we can go through and curry all the functions we've defined. For example, 'add' could be redefined as:

(define add (lambda (a) (lambda (b) ((b succ) a))))

In other words, instead of taking two arguments ('a' and 'b' as it was defined earlier), 'add' is now a lambda that takes just one ('a') and returns a new lambda that takes the second argument ('b') and does the calculation. Any function taking multiple arguments can be reduced to a chain of functions like this; each taking just one argument. This was one of the big contributions of Haskell Curry. It's more of a pain to call this new definition of 'add' but it works:

> (print ((add three) four))
7

Furthermore, if we want to go completely out of our minds, because of referential transparency we can go through our definition of 'fac' and replace all the references to various things we've defined ('sub', 'one', 'mult', 'if', etc.) with the bodies of those definitions (and in turn, replace any references in those bodies. For example, replacing "add" with "(lambda (a) (lambda (b) ((b succ) a)))" and inside that replacing 'succ' it's definition, etc. - we can do this blindly without breaking anything. And since 'fac' doesn't even refer to it's own name (due to the beautiful Y/Z Combinator) we can systematically reduce our 'fac' to only a bunch of functions calling functions and returning functions. Here's the result:

(define fac ((lambda (f) ((lambda (x) (f (lambda (y) ((x x) y)))) (lambda (x) (f (lambda (y) ((x x) y)))))) (lambda (f) (lambda (n) ((((lambda (c) (lambda (a) (lambda (b) ((c a) b)))) ((lambda (n) ((n (lambda (x) (lambda (a) (lambda (b) b)))) (lambda (a) (lambda (b) a)))) n)) (lambda (f) (lambda (x) (f x)))) (((lambda (a) (lambda (b) ((a (lambda (x) (((lambda (a) (lambda (b) ((b (lambda (n) (lambda (f) (lambda (x) (f ((n f) x)))))) a))) x) b))) (lambda (f) (lambda (x) x))))) n) (f (((lambda (a) (lambda (b) ((b (lambda (n) ((lambda (c) (c (lambda (a) (lambda (b) b)))) ((n (lambda (p) (((lambda (a) (lambda (b) (lambda (c) ((((lambda (c) (lambda (a) (lambda (b) ((c a) b)))) c) a) b)))) ((lambda (n) (lambda (f) (lambda (x) (f ((n f) x))))) ((lambda (c) (c (lambda (a) (lambda (b) a)))) p))) ((lambda (c) (c (lambda (a) (lambda (b) a)))) p)))) (((lambda (a) (lambda (b) (lambda (c) ((((lambda (c) (lambda (a) (lambda (b) ((c a) b)))) c) a) b)))) (lambda (f) (lambda (x) x))) (lambda (f) (lambda (x) x))))))) a))) n) (lambda (f) (lambda (x) (f x)))))))))))

> (print (fac seven))
5040

Notice that all we need is 'lambda' - it's the ultimate all right! Totally crazy! But it proves that once we boil everything away, what we're left with is the very essence of computation: only functions taking a single function as an argument and returning a function (of the same). That's The Lambda Calculus.

11月6日

Chasing the Tail

Recursion is absolutely ubiquitous as the loop control flow mechanism in a world without assignment. Familiar constructs such as for/while loops make no sense without mutation.

 

Here is a recursive definition of a recursive process for calculating factorial (in Scheme):

 

(define (factorial n)

  (if (<= n 1)

     1

     (* n (factorial (- n 1)))

  )

)

 

My previous post has a nice example of how the “shape” of the process can be seen by way of successive substitutions.

 

This now, is another recursive definition of factorial, but this time defining an iterative process using the common tactic of an accumulator:

 

(define (factorial n a)

  (if (<= n 1)

     a

     (factorial (- n 1) (* n a))

  )

)

 

Comparing these in the “Stepper” in DrScheme makes for a nice example:

 

 

The former builds up deferred multiplications while the latter accumulates the answer directly.

 

So what happens when we try this in C#?

 

using System;

 

public static class Tail {
   
public static int Factorial(int n, int a) {
       
if (n <= 1) return a;
       
return Factorial(n - 1, n * a);
    }

 

    public static void Main() {
        Factorial(7, 1);
    }
}

 

Watching in the debugger, you can see that a call stack is built and then collapsed even though this is clearly tail recursive.

 

 

Looking at the IL for this we can see that it’s doing a regular “call” and “ret” – silly C# compiler!

 

 

Tail recursion can be thought of as a “goto with parameters” and we can manually implement this if we like:

 

public static int Factorial(int n, int a) {
    start:
   
if (n <= 1) return a;
    a *= n; n--;
   
goto start;
}

 

But how horribly ugly! Using mutation and goto! Notice also that if a *= n; and n--; were reversed it would be a bug. As soon as you introduce assignment, bugs like this are possible.

 

Side note: I enjoy being one of the happy devs who’s moved to managed languages and longer has to worry about stack and heap corruption, memory leaks and buffer overruns. Next I want to move away from the store and branch instructions in our von Neumann machines. We all broke free of goto many years ago but most are still fighting with assignment to this day. Eliminating this whole class of bugs will be great.

 

Another example that comes to mind: Some people find it amazing to hear that in F# you only very, very rarely have any need at all for the concept of null (mainly only for backward compat with .NET libraries). Wouldn't you love to say, "NullRefException? What's that!?” Smile

 

Okay, back to recursion; lets try this again in F# this time:

 

let rec Factorial n a =
   
if n <= 1 then
        a
   
else
        Factorial (n - 1) (n * a)

Factorial 7 1

 

In the debugger, it’s apparently smart enough to eliminate the call stack! Excellent.

 

 

Let’s look at the IL:

 

 

Sweet, the compiler is doing the “sub”, “mul” and stomping on the original arguments (“starg.s”), then simply branching (“br.s”) back to the beginning. I have no problem with compiler-generated mutation and goto.

 

I’m curious now, if the compiler is smart enough to optimize tail recursion in the form of a function calling itself, what will it do with proper tail calls to other functions? It can’t be branching between functions:

 

let rec Even n =
    n <> 1 && (n = 0 || Odd (n – 1))
  

And Odd n =
    n <> 0 && (n = 1 || Even (n – 1))

Even 5

 

Looking in the debugger, we can see that Even 5 calls Odd 4, which calls Even 3, calling Odd 2, which finally calls Even 1 and returns false; all of this without a call stack.

 

 

Nice. But how? As usual, the IL gives it away:

 

 

The “.tail” prefix tells the JIT compiler that stack frame can be recycled before the following “call.” It turns out that even without this prefix, the JIT compiler can potentially be smart enough to optimize. Jomo Fisher has a nice post on this.


I just gave a brownbag talk on this. Here's the deck if you're interested.

10月30日

The Great Debate

I found this interview/debate with Mads Torgersen (C# guy), Joe Armstrong (Erlang guy) and Erik Meijer (Haskell guy) very entertaining!
It's a classic debate. I remember hearing it in the 25-year-old SICP lectures in which Hal Abelson said,

“Generally, I think what you're seeing is that we're running across what I think's a very basic problem in Computer Science; which is how to define languages that somehow can talk about delayed evaluation but also be able to reflect this view that there are objects in the world. How do we somehow get both? I think that's a very hard problem and it may be that it's a very hard problem that has nothing to do with Computer Science. It really is a problem with having two very incompatible ways of looking at the world.”

But hey, before you start thinking that Erlang must be the answer to all the world’s problems Smile, you should read this post showing how to do the same message passing style w/async workflows and MailboxProcessor in F#: http://strangelights.com/blog/archive/2007/10/24/1601.aspx

10月24日

Map / Reduce / Filter

I just did a little Functional Programming brownbag talk today. One example that went over pretty well was this:

double CheapGasNearby(IEnumerable<GasResult> results)
{
   
double min = double.MaxValue;
   
foreach (GasResult r in results)  {
       
if (r.Distance < 5.0)  {
           
double price = r.Price;
           
if (r.Name == "Safeway")
                price *= 0.9;
           
if (price < min)
                min = price;
        }    }
   
return min;
}

This works to find the minimum price for gas within 5 miles; taking into account a 10% Safeway discount. Ahhh! Mutation and mixing of intent all over the place!
 

Let’s see if we can, most importantly, separate out the intentions and also get rid of the use of assignment:

double CheapGasNearby(IEnumerable<GasResult> results)
{
    double min = double.MaxValue;
    foreach (GasResult r in results)  {
        if (r.Distance < 5.0)  {
            double price = r.Price;
            if (r.Name == "Safeway")
                price *= 0.9;
            if (price < min)
                min = price;
        }    }
    return min;
}

Examining the code in red, you notice that it's essentially doing a map (just converting a collection of GapResults to adjusted doubles), and the green is a reduce operation (threading the min accumulator throughout the iteration) and the purple is obviously a filter. This can be rewritten in a much more straightforward way using the functional extension methods hanging off of IEnumerable in .NET 3.5+:

double CheapGasNearby(IEnumerable<GasResult> results)
{
    return results
       
.Where(r => r.Distance < 5.0)
       
.Select(r => r.Price * (r.Name == "Safeway" ? 0.9 : 1.0))
       
.Aggregate(double.MaxValue, (m, p) => p < m ? p : m));
}

Of course there’s already a Min() method available and additionally it’s even more succinct using LINQ keywords:

double CheapGasNearby(IEnumerable<GasResult> results)
{
    return (from r in results
         where r.Distance < 5.0
         select r.Price * (r.Name == "Safeway" ? 0.9 : 1.0)
        ).Min()
}

Why would we ever want to write it in the "mini-Rube Goldberg machine" imperative style?

 

Here's the brownbag deck if you're interested...

9月21日

F# For Fun

Mr. GeekRaver and I were walking between buildings and, for some reason, talking about how silly it is that good ol' Minesweeper was "glossed up" for Vista. He said he had written it for DOS in some tiny amount of C code (http://www.bradygirl.com/Work/mine.c).

His explanation of little tricks to make the implementation simple (e.g. a traverse() function that walks the board applying a passed in function to each cell) sounded like FP to me. So, here it is in about 40 lines of F# (plus another 50 for UI). Now, my challenge to him is to beat that using Python (his current kick) this time...

Mines screenshot

 
#light
#nowarn "57" // multiple additive results from sequence expressions
 
(*
This is a simple implementation of the Windows game Minesweeper.
Ideas were shamelessly stolen from my office-mate Gram's DOS version:
http://www.bradygirl.com/Work/mine.c
Funny enough, the coolest part of his C code is his functional style.
His traverse() function is essentialy a 'map' used to walk the board
applying a passed-in function (check_neighbors, etc.) and also
recursive_expose() itself is pretty cool. Let's try it in a proper
functional language:
*)
 
open System
open System.Drawing
open Windows.Forms
 
let w = 9  // width of mine field
let h = 9  // height
let d = 10 // 1:10 mine density
 
type State = Unknown | Flag | Expose
 
let randomField = // init field w/randomly placed mines
    let r = new Random(int DateTime.Now.Ticks)
    Array2.init w h (fun y x -> (r.Next(d) = 0), Unknown)
 
let adjacentCoordinates x y = [ // list of adjacent x,y pairs
    for i in x - 1 .. x + 1
    for j in y - 1 .. y + 1
    when (i <> x || j <> y) && // not including x,y itself
    i >= 0 && i < w && j >= 0 && j < h // not off edges
    -> (i, j) ]
 
let adjacentCells m xy = // list of adjacent cells
    List.map (fun xy -> m.[fst xy, snd xy]) xy
 
let countMines = Seq.sumByInt (function (true, _) -> 1 | _ -> 0) // given Seq of cells
 
let countFlags = Seq.sumByInt (function (_, Flag) -> 1 | _ -> 0)
 
let setCell f m x y = // apply f to snd of cell x,y of m
    Array2.mapi (fun i j c -> if i = x && j = y then (fst c, f (snd c)) else c) m
 
let setFlag = // toggle Flag, but leave already Exposed as is
    setCell (function Unknown -> Flag | Flag -> Unknown | Expose -> Expose)
 
let setExpose = setCell (function Flag -> Flag | _ -> Expose) // leaved Flagged as is
 
// this is the only interesting part :-)
// we automatically expose any cells known to be safe based on the exposed
// mine counts and surrounding flags (players incorrectly flagging cells may blow up!)
let rec autoExpose m xy =
    match xy with
    | [] -> m
    | (x, y) :: t ->
        if (snd m.[x, y]) = Unknown then
            let n = setExpose m x y
            let a = adjacentCoordinates x y
            let c = adjacentCells n a
            autoExpose n (if countFlags c >= countMines c then (a @ t) else t)
        else autoExpose m t // already Exposed or Flagged
 
// that's it, the rest is UI:
 
let form =
    let field = ref randomField
    let s = 20 // grid size
    let paintField (g : Graphics) =
        let paintCell (g : Graphics) x y c =
            let i = x * s // x-coordinate
            let j = y * s // y-coordinate
            let l = i + 1 // left (with 1 pix inset)
            let t = j + 1 // top
            let (r : int) = i + s - 1 // right
            let b = j + s - 1 // bottom
            let i = s - 1 // inner size
            let f = new Font(FontFamily.GenericSansSerif, 10.0f, FontStyle.Bold)
            match c with
            | (_, Unknown) -> // "embossed"-looking highlights
                g.DrawLine(Pens.DarkGray, r, t, r, b)
                g.DrawLine(Pens.DarkGray, l, b, r, b)
                g.DrawLine(Pens.White,    l, t, r, t)
                g.DrawLine(Pens.White,    l, t, l, b)
            | (   _, Flag)   -> g.FillRectangle(Brushes.Green, l, t, i, i)
            | (true, Expose) -> g.FillRectangle(Brushes.Red,   l, t, i, i)
            | (   _, Expose) ->
                g.FillRectangle(Brushes.Gray, l, t, i, i)
                let n = (countMines (adjacentCells !field (adjacentCoordinates x y))).ToString()
                if n <> "0" then
                    let b = match n with
                            | "1" -> Brushes.LightBlue
                            | "2" -> Brushes.LightGreen
                            | "3" -> Brushes.LightCoral
                            | _   -> Brushes.White
                    let m = g.MeasureString(n, f)
                    g.DrawString(n, f, b,
                                 float32 l + (float32 s - m.Width)  / 2.0f,
                                 float32 t + (float32 s - m.Height) / 2.0f)
        g.Clear(Color.Gainsboro)
        Array2.iteri (paintCell g) !field // note: use of currying paintCell
    let f = new Form(Text = "Mines", ClientSize = new Size(w * s, h * s), Visible = true)
    f.Paint.Add(fun a -> paintField a.Graphics)
    f.MouseDown.Add(fun a ->
                    let i = a.X / s
                    let j = a.Y / s
                    field := if a.Button = MouseButtons.Left then
                                autoExpose !field [(i, j)]
                             else
                                setFlag !field i j
                    let c = (!field).[i, j]
                    if fst c && snd c = Expose then // exposed a mine?!
                        field := Array2.map (fun c -> (fst c, Expose)) !field // expose everything
                        f.Refresh()
                        MessageBox.Show("Boooooom!\nTry again.") |> ignore
                        field := randomField // start over
                    f.Refresh())
    f
 
Application.Run(form)
9月8日

Syntactic Sugar Is Sweet!

I’m really loving working in F#! It may become my primary language for the next half-decade. Through the early 90s it was C++, the late 90s was spent drinking the Java Kool-Aid®, the 2000s has been C# (with a sad couple-year relapse to C++ in there), now I think I’m ready for a completely different branch of the language tree. ML is a good branch and functional languages are certainly the future - most likely coming to the masses in the form of more popular languages being infused with functional idioms. C# 3.0 is a deliberate step in that direction.

Scheme is still my favorite for pure elegance and simple beauty, but for an everyday tool, simplicity of the language itself is not what’s important. I do like the Scheme motto of, “…removing the weaknesses and restrictions that make additional features appear necessary…” and I appreciate that the simplest solution is often also the most general one. Scheme’s exploration of how far this can be taken is amazing.

On the other hand, syntactic sugar sure is sweet! F# is wonderfully succinct and powerful! As a professional tool, this is exactly what I’m looking for. At first I felt kind of bad for favoring F# over Scheme; thinking it was my Microsoft influence showing. Microsoft certainly gets it wrong sometimes when it comes to packing too many features into consumer products. However, I think that professional tools, and especially programming languages targeting “high end” users, are very different from casual-use products. The learning curve is steep, but is far outweighed by the all-day-every-day productivity that comes from feature richness. I don’t care if the language is complicated to implement (Don Syme can worry about that). I only care about keeping my solutions written within the language simple. As a professional dev, I want the power to write terse and simple code.

Matz (the Ruby guy) said it nicely in Beautiful Code (Chapter 29 – Treating Code As an Essay): “Simplicity is one of the most misunderstood concepts in programming. People who design languages frequently want to keep those languages simple and clean. While the sentiment is noble, doing this can make programs written in that language more complex. … while [Ruby] is far from simple, it supports simple solutions for programming. Because Ruby is not simple, the programs that use it can be.” He also quoted Mike Cowlishaw (the REXX guy): “The general principle is that very few people have to implement interpreters or compilers for a language, whereas millions of people have to use and live with the language. One should therefore optimize for the millions, rather than the few. Compiler writers didn’t love me for that…”

8月12日

So Many Books, So Little Time...

I just finished my second reading of Robert Pickering’s book, Foundations of F#. Why read it twice? Well to be honest, I didn’t understand it the first time Tongue out. Also, the structure of the book is such that you don’t learn enough to be useful until you’re halfway through. That makes it difficult to remember the first half! Still, it’s a good book. All the basic information is there and presented clearly, and besides it’s the only F# book currently in print! So it has to be the best out there. Don Syme’s, Expert F# is coming next; can’t wait.

More promising is Paul Hudak’s, The Haskell School of Expression which I’m in the middle of at the moment. Not that I really want to learn Haskell (although surprisingly similar to F#). I’m hoping to learn more about the functional way of doing things. It’s a fun book because it teaches enough to get started and immediately jumps into building things in an interesting problem domain (geometry and a graphics library). You begin to feel that each new thing you learn is a new toy to play with; Its fun – as programming should be. Also, as you pick up new tricks, he takes you back to revisit solutions from previous chapters and to refactor out some of the ugliness. You quickly appreciate the value of things that would have otherwise gone unnoticed without having first done it the hard way.

This is how teaching a new language should be done. Show a little bit and start using it right away. Then teach a bit more and start using that. Don’t worry too much about presenting each thing exhaustively or in a well-structured order. Also, don’t worry about letting the learner jump in with inadequate knowledge to do things properly. That will only help lead to learning opportunities where you can later add to the toolbox and show how to do it right.

7月10日

Monkey Talk

I’ve finished up my little Scheme interpreter. It’s pretty cool, and amazingly simple. I believe Scheme is my favorite language of all time. It’s incredibly elegant. I do have an appreciation for the convenience of languages with more syntactic sugar but for pure minimalistic beauty, Scheme takes the cake!

So, obviously I can parse text source code and run it in my little engine, but I’ve also been working on a “Visual Scheme” editor. The idea is that you snap together blocks representing primitive operators and functions you’ve defined. Rather than build an AST with nested parentheses you build it with a tree of S-Expression blocks. To calculate 1 + 2, just snap “1” and “2” atoms onto the “+” operator:

clip_image001

It’s pretty cool to use. The blocks snap together as you drag them near each other. I’m thinking of making the little “nubs” different shapes to enforce type safety. You can hover over an operator to evaluate it. You can build up expressions and, just like Scheme, there are no operator precedence rules; it’s all a matter of how you stack them. For example, the infix notation “(1 + 2) * 3” becomes:

clip_image002

You can see that in prefix notation and full parenthesis it’s “(* (+ 1 2) 3)”. If you really want the times operator to take precedence to get “1 + 2 * 3” then rearrange them as:

clip_image003

Again, it’s more clear in prefix notation that this “(+ 1 (* 2 3))” is different from “(* (+ 1 2) 3)”. You can still hover over sub-expressions (highlighted in red) to evaluate them separately if you like:

clip_image004

As usual, the “hello world” of functional languages is the factorial function so here goes:

clip_image005

You can see in the small black print that the blocks become the body of a function called “Self”, taking an “n” argument. (Self 7) evals to the correct answer: 5040. You’re free to evaluate sub-expressions as usual but if you try to evaluate a recursive expression without a base case you should expect a stack overflow :

clip_image006


I mentioned (see May 18th post) that I want to build a functional reactive environment suitable for kids to learn to program. I’m still pretty impressed with Scratch and with how easy it is for my kids to pick up and start building cool things. Still, I feel like I was ruined a bit by early exposure to BASIC instead of Lisp growing up :-). It would be a fun experiment to see how well kids could pick up Lisp in a Scratch-like environment.

I don’t really want to knock Scratch. It’s nicer than other attempts such as Squeak or Phrogramming. My problem with it though is that it teaches the imperative mind set and does so in the worst possible way. For example, there is no such thing as a function call at all! The best you can do is to stuff data into globals and then broadcast a message. Wow, is that a horrible habit to be teaching!

I at least want to see if it’s possible to build a reasonable functional reactive system. Quartz Composer (see May 22nd post) is pretty close but I don’t have a Mac. Also, from what I gather, Quartz operates at a higher level than I want. I don’t want a data binding GUI. I do want to wire up properties between modules, but I want also to be free to write logic at the lowest levels by “snapping” together expressions – building higher and higher levels bottom-up ultimately from true primitives.

So here’s the idea – top down: You have “modules” which represent things in the world – something like the sprites in Scratch. Modules don’t have a fixed set of properties though and instead can have various properties of your choosing and can render those properties however you see fit. There are some primitive inputs into the system (e.g. key presses) and module property values can be defined in terms of these input and/or of other properties. Property values are updated at regular time intervals (e.g. 1/20th second). So there is state in the system (property values over time) but the definition of how the state should change from one time slice to the next is a set of pure functions.

For example, here I want to build a Sumo Robot simulator (something like the MS Robotics Studio competition at MEDC). For the moment, I’m most concerned with how exactly you define properties as functions of other properties and of the system inputs. To be honest, the current inputs and the bots are “hard coded” modules but the idea is that you’ll be able to specify these in a general way. You’ll be able to introduce new modules, define their properties and declare the rendering of them as functions taking in properties and emitting a kind of markup to be rendered.

clip_image008

In this instance, each “bot” module has a location in the “ring” (polar coordinates with radius zero = center, one = edge) and each bot has a direction (radians) and a speed (ring radius units per second – negative for reverse). They render as simple blue circles with an arrow indicating direction.

Each property begins with a default value and is then recomputed each “time slice.” The computation is a pure function of properties from the previous time slice. The one exception is the primitive input properties; in this case I have four key up/down/left/right boolean properties saying whether the given key is currently pressed.

One way to think of functional reactive programming is to imagine that the properties are rows in an Excel spreadsheet and columns represent time. Cells in a given column can only be pure functions of cells from the previous column. Then you just “fill right” to simulate time – pure functional definitions but still a concept of state and time.

Here’s the code for one of the bot’s Direction property:

clip_image009

The inputs are Control Left (cl) meaning the left key is currently being pressed, Control Right (cr) and My Direction (md). So you can see that the direction changes by +0.1 or -0.1 depending on the Left/Right keys being pressed or else remains unchanged. Pretty cool! Now you can spin it around with the arrow keys!

Similarly for the bot’s speed - using Control Up (cu), Control Down (cd) and My Speed (ms):

clip_image010

Excellent! Now you can drive it all around the ring – it’s fun already! Bots need not only be driven directly by the keyboard. They can be a function of any property in the system (including the other bot’s location/direction/speed). Here, we use His Direction (hd) to say that the other bot should always point in the opposite direction (in radians):

clip_image011

And here we say that the speed should be half of His Speed (hs):

clip_image012

Now you drive one bot manually and the other follows in a slower mirror image. Fun, fun! You’ll have to use your imagination a bit here. You can imagine defining helper functions to do things like calculate the angle to make one bot point at the other or to calculate the distance between bots. Then build atop that some attack and evasion strategies. For example, to escape just point away and run, then dodge when pinned against the edge.

The composability of pure functions is wonderful – one of the primary benefits of FP I believe. This could lead to an ecosystem much richer than Scratch where people share their ideas at various levels. One issue is how to handle the cross-module dependencies. I’m thinking that perhaps modules will not be able to “see” each other. Instead, they’ll expose inputs as part of their interface and you’ll be able to wire properties of one modules to the inputs of another. This way modules can be reused out of context. Try making a sprite that’s sharable this way in Scratch – very difficult! This is something like the OO principle in which concrete classes are always made to implement an interface or abstract base class and only ever refer to each other as abstracts (not that I always do this myself ).

Anyway: Primitives assembled into functions, in turn assembled into higher and higher level functions, finally driving fully self-contained modules that take part in time and may have a visual representation. Sharing at all levels without dependencies and all done by dragging together blocks and wire diagrams. That’s the idea! We'll see how it goes...

6月6日

Little Schemer

I've just finished reading through Daniel P. Friedman's excellent little book The Little Schemer and immediately ordered The Seasoned Schemer and The Reasoned Schemer to continue the adventure. These are great books for someone new to Scheme; using a very interesting and fun approach of not explicitly explaining anything, but instead asking a series of small questions and after seeing enough answers to similar problems you start to naturally “get it”. It’s funny too; using foods and silly things in all the examples and saying things like, “This space reserved for jelly stains.” at the end of a chapter.

I’ve been using Dr. Scheme which is a wonderful little environment, but now I’ve been wanting to write my own so that I can embed it in another project I’m cooking up (something like a functional Scratch-like environment). 

Bill Hails has very nice series on the implementation of PScheme (a Scheme interpreter written in Perl). I want to write mine in C# or F# and make a compiler rather than interpreter but the architecture here is great (pretty much following what’s laid out in SCIP) and the explanation is wonderfully clear. As a Go player, I especially liked his comment in the introduction, “… if C is the chess of programming languages, then Scheme is more like Go.”

5月22日

Quartz Composer

Apple's Quartz Composer looks pretty close to what I'd like to build! Too bad I gave up on the Mac around System 7.5 when I got tired of waiting for an OS that was stable (doesn't crash ten times a day) and modern (i.e. pre-emptive multitasking, virtual memory, etc.). Now I wish I had one to play with
 
Quartz is essentially a pure FRP language with a very nice GUI; probably suitable for kids:
 
4月23日

The SECD Machine

A year ago my officemate pulled off the amazing feat of writing a JavaScript compiler and virtual machine (not interpreter) in the span of just a few weeks for a project we were working on. He hadn’t even used JavaScript before. He just read the ECMA spec and implemented the language just like that. I was pretty blown away! Anyway, this got me interested in trying to make a compiler and VM of my own (for a much simpler language).

He recommended I do a tiny Lisp variant and a simple stack-based SECD machine and recommended this wonderful little orange book: Functional Programming Application and Implementation. It’s an oldie but a goodie from 1980. I’m on my third time reading it now! The first time it just started to sink in and made me want to implement the “Lispkit Lisp” he specs out in the book. So I had a fun couple of nights doing that, and then read it again; working through the exercises. It's a great book.

Below is the complete compiler and SECD machine in C# - it’s only a few hundred lines! I want to (sometime) next do a simple Scheme compiler in C# 3.0 this time and produce an expression tree (System.Linq.Expression) and compile to IL. That would be pretty cool.

Here’s a sample run to return X + Y * Z where X = 1, Y = 2, Z = 3:

    public class Program
    { 
        static void Main(string[] args) 
        { 
            string input = "(1 2 3)"; 
            string source = "(Lambda (X Y Z) (Add X (Multiply Y Z)))";
  
            Machine machine = new Machine(source, input);

           
Console.WriteLine("[Input: {0}]", input);
            Console.WriteLine("[Program: {0}]", source); 

            int i = 0;
            do
            {
                Console.WriteLine("Step {0} ----------------------------------------", i++);
                Console.WriteLine(machine.ToString());
            } while (machine.Step());
        }
    }

And here's the output - (7) ends up on the stack after eight cycles:

[Input: (1 2 3)]
[Program: (Lambda (X Y Z)(Add X (Multiply Y Z)))]
 
Step 0 ----------------------------------------
[Stack: ((1 2 3))]
[Environment: Nil]
[Control: (LDF (LD (0 2) LD (0 1) MUL LD (0 0) ADD RTN) AP STOP]
[Dump: Nil]
 
Step 1 ----------------------------------------
[Stack: (((LD (0 2) LD (0 1) MUL LD (0 0) ADD RTN))(1 2 3))]
[Environment: Nil]
[Control: (AP STOP)]
[Dump: Nil]
 
Step 2 ----------------------------------------
[Stack: Nil]
[Environment: ((1 2 3))]
[Control: (LD (0 2) LD (0 1) MUL LD (0 0) ADD RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 3 ----------------------------------------
[Stack: (3)]
[Environment: ((1 2 3))]
[Control: (LD (0 1) MUL LD (0 0) ADD RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 4 ----------------------------------------
[Stack: (2 3)]
[Environment: ((1 2 3))]
[Control: (MUL LD (0 0) ADD RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 5 ----------------------------------------
[Stack: (6)]
[Environment: ((1 2 3))]
[Control: (LD (0 0) ADD RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 6 ----------------------------------------
[Stack: (1 6)]
[Environment: ((1 2 3))]
[Control: (ADD RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 7 ----------------------------------------
[Stack: (7)]
[Environment: ((1 2 3))]
[Control: (RTN)]
[Dump: (Nil Nil (STOP))]
 
Step 8 ----------------------------------------
[Stack: (7)]
[Environment: Nil]
[Control: (STOP)]
[Dump: Nil]
 
Done ------------------------------------------

Just a few hundred lines of code for the compiler and virtual machine. If you want the complete VS project with unit tests and all. Have fun!

4月18日

“Odd” Puzzle

Here’s a little coding puzzle: Can you think of a way to define a pair of functions to test for even-ness and odd-ness of a positive integer argument? Here's the catch: you can't use bitwise operators, mod or division? Seriously… see if you can think of a solution!

...

I thought this “mutually recursive” solution was pretty cute:

// F#
let rec even n = (n<>1) && ((n=0) or (odd (n-1)))
and odd n = (n<>0) && ((n=1) or (even (n-1)));;

; Scheme (BTW, there's already even? and odd?)
(

define (even n) (and (not (= n 1)) (or (= n 0) (odd (- n 1)))))
(define (odd n) (and (not (= n 0)) (or (= n 1) (even (- n 1)))))
4月17日

Sussman the Lisp Wizard

Some of these SICP lectures crack me up! In the “Metacircular Evaluator”, Professor Sussman writes up on the board an implementation of Lisp in Lisp. Before he gets started, he says, “We’re getting very close to the spirit inside the computer now… I have to show some reverence and respect…” and he puts on a jacket and that silly hat. He writes the whole thing up on the board and then stands back and says, “Let’s just look at it for a while…” while they play the theme from 2001: A Space Odyssey. Hilarious… maybe you just had to be there…

It’s interesting from a theoretical point of view and practical as a way to then easily play with language modifications or to invent new languages (as Abelson does, making something like Prolog, later in the lectures on “Logic Programming”).

Edited down (and sped up) to under 3 minutes:

 
 
Video: Wizard Gerald Sussman
4月16日

Streams baby!

These SICP lectures are great I tell ya! The two lectures on Streams (6a/6b) talk about implementing things with lazy lists. His examples are in Scheme but here’s my translation to C# using some of the new features in 3.0. For example, here is a lazy list of all integers starting with n:

public static IEnumerable<int> Integers(int n)
{
    while (true)
       
yield return n++;
}

Cool, eh? (That can be done in 2.0 actually but we're getting to the good stuff...) It’s a bit strange to think of this as essentially an infinitely long List<int>, but why not? What I got out of the lectures was the idea that rather than think of variables changing over time, we can think of lazy lists as representing the complete set of values - fixed in time. Abelson said something funny about it: you can think of the values all being there in the same way that you think of your money being in your bank account – at least it’s there when you go to look for it and that’s all you should care about.

Wait a minute though, that code is using mutation! Well, sure it could be implemented as something like… 

public static IEnumerable<int> Integers(int n)
{
   
yield return n;
   
foreach (int i in Integers(n + 1))
       
yield return i;
}

… but that’s quite a bit less efficient and the former is very well contained mutation. I don’t want to be a pure functional zealot! I’m still debating whether to really pop the red pill...


So what can we do with an infinitely long list of ints anyway? Certainly we can’t just foreach over all of them. That would be a run on the bank!’ With some of the new extension methods hanging off of  IEnumerable  we can do things like Integers(1).Take(10) to get 1-10 or we can filter (Where()) or map (Select()) or reduce (Aggregate()) them. How ’bout the good ol’ factorial function using our Integers stream this time:

public static int Factorial(int n)
{
   
return Integers(1).Take(n).Aggregate(1, (a, b) => a * b);
}

Pretty simple. It works by taking the first n integers and multiplying them all together (the (a,b)=>a*b lambda expression) seeded with 1.


How about a lazy list of Fibonacci numbers using recursion:

public static IEnumerable<int> Fibs(int a, int b)
{
   
yield return a;
   
foreach (int i in Fibs(b, a + b))
       
yield return i;
}

Fun! Now we can say var fibs = Fibs(0, 1); and get, what can be thought of as, the complete list of Fibonacci numbers. To try it out, we can add a Print() method to IEnumerable  (extension methods are such a cool feature).

public static void Print(this IEnumerable<int> list)
{
   
foreach (int i in list)
       
Console.Write("{0}, ", i);
   
Console.WriteLine();
}

So now we can say fibs.Take(20).Print(); and get 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181. Nifty.


Here’s the finale. Everyone knows the Sieve of Eratosthenes for finding prime numbers. The usual way of implementing it is to cross off non-primes in a giant bit array or something like that. I remember when we first got our 64-bit dev boxes with 8GB of RAM on the Search team. The first thing Dan and I did was to calculate all the primes between 1 and 100-billion using up more memory for the bit array (of only odd numbers) than is even addressable in 32-bits.

Here is a very elegant (though much less performant) way to do it with streams:

public static IEnumerable<int> Sieve(this IEnumerable<int> list)
{
   
int first = list.First();
   
yield return first;
   
foreach (int j in list.Where(x => x % first != 0).Sieve())
       
yield return j;
}  

For the given list of integers (it's an extension method of IEnumerable<int>), it returns the first element followed by the rest of the list filtered down to only those that are not divisible by the first (using the Where() extension method - the same one corresponding to the Linq keyword ‘where’ - and using a lambda expression for non-divisibility).

So, for example, a list of ints starting with 2, 3, 4, 5, 6, 7, … would return 2 followed by only odd numbers 3, 5, 7, … But notice that the filtered list is recursively run through Sieve() which will return, of the list of ints not divisible by 2, the ones that are also not divisible by 3, and of those the ones not divisible by 5, then filtered again by 7, and 11, etc. This is the Sieve of Eratosthenes in just a few lines. Absolutely beautiful! To kick it off, we just say:

var primes = Integers(2).Sieve();

… and voila! We have a lazy list of all primes. We can now say:

Console.WriteLine(primes.ElementAt(20));

… and out comes 73. Or we can say:

primes.Take(100).Print();

… and get 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,

Or here’s a silly way to get the first 15 primes the hard way using some of the other IEnumerable extension methods:

primes.Take(10).Concat(primes.Skip(5).Take(10)).Distinct().Print();

We can now think of the range of a function, not as the result of computation, but as if it were just plain data.