Showing posts with label F#. Show all posts
Showing posts with label F#. Show all posts

Thursday, February 26, 2009

Fluent language in FsStory

A nice feature for a story runner is to be able to provide arguments in a story sentence, like this:

ATableWithNumberOfLegs 4

This example is not hard to understand, but there's some mental translation going on, since the order of the words is all screwed up. Let's try another one:

TheNumberOfLegsOfATableIs 4

Better, but still not good. First, it's longer than the previous example. Second, even if the grammar is correct, the word order is, well, unusual.. ;)

What about this?

ATableWith 4 Legs

Now we're talking!

Here's a bigger and more complete example:

[<Fact>]
let tableLegsScenario =
given (ATableWith 4 Legs)
|> whens (ICutOf 1 Leg)
|> thens (ItHasOnly 3 LegsLeft)


Note: As far as I know, RSpec/Cucumber is the only story runner(s) that is able to use variables inside a story sentence.

The nice thing about this is that I didn't have to change FsStory itself to make it work. Not a single line. So, what's the trick?

If you split up a story sentence like this, you have to prepare the step definition code (the behind-the-scenes code) in a certain way:

let ATableWith = fun n _ -> ... do something here ...

..or if you prefer, without a lambda:

let ATableWith n _ = ... do something here ...

Then you have to define Legs:

let Legs = id

As you see, in this case, it was just a matter of discovering the usage, rather than implementing it in the language. Honestly, I had no idea of this usage when I started to write on FsStory. This is clearly one of the reasons why I like internal DSLs!

Exercise: How would you implement the step definition for the following story sentence?

given (ATableWith 4 LegsAnd 2 Chairs)

Cheers!

Monday, February 9, 2009

[Announce] FsStory, executable stories in F#

Since Claudio Perrone's talk on Øredev, I have been thinking about what his MisBehave would look like in F#. In his talk, Claudio also mentioned Cucumber, a story runner written in Ruby. My plan was to make a lightweight DSL for writing stories in F# code, with the story parts separated from the implementation parts.

Currently, FsStory enables the developer to write user story scenarios (in Given/When/Then form) in F# code, like this:
#light

open FsStoryRunner
open MutatedTurtleMovesImpl
open Xunit

(*
In order to impress my friends
As a .NET programmer
I want to draw funny fractal pictures
*)

[<fact>]
let MoveTurtleToPosition() =
given ATurtle
|> andGiven IsRotated90DegreesToTheRight
|> whens (TurtleWalksSteps 9)
|> thens (TurtleIsLocatedAt (0,9))
|> endStory

Did you notice [<fact>] attribute just before the function definition? It is a xUnit.net specific attribute, telling xUnit.net that the function is a runnable test. So, why xUnit.net? Answer: xUnit.net is the currently the only test framework that runs static test methods, which is what F# functions compiles to.

Note: If you think that the story above is too low level to be a "good" user story, you're right, but it's just an example..

The "ATurtle", "IsRotated90DegreesToTheRight", "TurtleWalksSteps", etc, are functions that you have to implement yourself. What these functions do is not FsStory's business, except that they have the same type. It's a good thing to think about this in advance.

If you're testing something object oriented, i.e. a C# project, then you're probably have to let the functions have the type () -> (). That is, they take no argument and return void, in C# lingo. You'd also need a mutable variable to accomplish this.
#light

open Turtle
open FsxUnit.Syntax

let mutable turtle = new Turtle() // turtle must have type Turtle

let ATurtle () = turtle <- new Turtle() // For reuse in same story let MovesOneStepForward () = turtle.Go() let IsMovedOneStepForward () = turtle.Position.X |> should equal 1 let RotationIs angle () = turtle.Direction |> should equal 0.0
It's up to the developer what library she wants to use for her assertions. In this example, FsTest was used, but she could go for NUnit or NBehave or something else. I hadn't actually tried this and do not longer think this will work. Either use xUnit.net or FsTest (which is based on xUnit.net).

Another style is to work with immutable objects. One example of immutable objects are value objects, in DDD. Immutable objects correspond well to functional programming principles. Here is an example of an implementation of a scenario when an immutable object is used in the SUT (System Under Test).
let ATurtle () = new TurtleImmutable()
let IsRotated90DegreesToTheRight = fun (turtle : TurtleImmutable) -> turtle.Left()
let TurtleWalksSteps steps = fun (turtle : TurtleImmutable) -> turtle.GoSteps(steps)
let TurtleIsLocatedAt (x,y) = fun (turtle : TurtleImmutable) -> turtle.Position |>
should equal (new Position(x,y)) ; turtle

To clarify, all methods on the (immutable) turtle return a new turtle and that turtle is returned and then passed in as an argument to the next test function (by FsStory). As you might have spotted, the example uses a lambda, an anonymous functions (the "fun") instead of specifying an argument explicitly. It's a good thing to get a running story before actually implementing the logic and assertions. Using the function "id" (just returning the argument) on the right-hand side is very helpful for getting everything to run.

You can find FsStory at http://www.codeplex.com/fsstory.

Tuesday, October 28, 2008

My first F#, Binary Chop

Yesterday, I really felt like trying out F#. To get some inspiration, I visited PragProgs katas, and chose Kata Two -- Karate Chop. Or, actually, I just implemented a "functional" solution. I tried to make an imperative pointer-based solution (which I might post later, when I have resolved a strange bug). Anyway, I had never coded F# before, so there might be a few places where I could have e.g. chosen a library function instead of implementing it myself. If you have any suggestions or general comments, please post them!

By the way, is there any way to program in literate F#?
#light
First, a few helper functions for triples.
let fst3 (a,b,c) = a
let snd3 (a,b,c) = b
let trd3 (a,b,c) = c
Define the middle index, for simplicity return 0 if list is empty.
let middleIndex xs = if List.is_empty xs then 0 else (List.length xs - 1)/2
Define a function that returns the middle element of a list, and two functions that returns the first/last remaining halfs. Note that there might not be a middle element, so we use the option type.
let firstHalf xs = Seq.take (middleIndex xs) xs

let middleElem xs =
match (xs) with
| [] -> None
| xs -> Some (xs.Item (middleIndex xs))

let lastHalf xs =
match xs with
| [] -> Seq.empty
| xs2 -> Seq.skip (middleIndex xs + 1) xs2
Let us group the functions in a convenient triple.
let splitInHalf xs = (firstHalf xs, middleElem xs, lastHalf xs)
Now, define a recursive function that 1) splits the list in three parts 2) reuse some definitions 3) return "None" if middle is empty 4) otherwise we can test the middle for equality, if equal then return the current index 5) if not equal, choose appropriate half and recurse.
let rec exists x xs i = 
let triple = splitInHalf xs in //1
let maybeMiddle = snd3 triple //2
let firstPart = Seq.to_list (fst3 triple)
let lastPart = Seq.to_list (trd3 triple)
if Option.is_none maybeMiddle then None //3
else let middle = Option.get maybeMiddle in //4
if x.Equals middle then Some(i) //5
elif middle > x then exists x firstPart (middleIndex firstPart)
else exists x lastPart ((i+1) + middleIndex lastPart)
This is the function a user would call.
let public ex x xs = exists x xs (middleIndex xs)
Some tests, just to check, plus a helper function for equality over options.
//Tests

let eq x y = if Option.is_none x then Option.is_none y else x.Equals y

let res = [
ex 3 [];
ex 3 [1];
ex 1 [1];

ex 1 [1;3;5];
ex 3 [1;3;5];
ex 5 [1;3;5];
ex 0 [1;3;5];
ex 2 [1;3;5];
ex 4 [1;3;5];
ex 6 [1;3;5];

ex 1 [1;3;5;7];
ex 3 [1;3;5;7];
ex 5 [1;3;5;7];
ex 7 [1;3;5;7];
ex 0 [1;3;5;7];
ex 2 [1;3;5;7];
ex 4 [1;3;5;7];
ex 6 [1;3;5;7];
ex 8 [1;3;5;7];

]

let answers = [None; None; Some 0;
Some 0; Some 1; Some 2; None; None; None; None;
Some 0; Some 1; Some 2; Some 3; None; None; None; None; None
]

let asserts = Seq.for_all2 eq res answers
asserts
Now, I must say that I had a real good time developing this! Ok, some minor things didn't went as smoothly as I'd hope for, but it was actually the first time that I tried F#. I've never had such a good experience with a language the first day of use.

I will definitly be posting more F# posts in the future!

Cheers

Tuesday, September 23, 2008

A thought on F#

A while ago I read this blogpost by Phil Wadler. The post is a comment on an article from an issue of Journal of Functional Programming. In that, Yaron Minsky and Stephen Weeks from Jane Street Capital talks about their experiences with functional programming on Wall Street. Wadler quotes from the article:
When we first tried switching over from VB to C#, one of the most disturbing features of the language for the partners who read the code was inheritance. They found it difficult to figure out which implementation of a given method was being invoked from a given call point, and therefore, difficult to reason about the code. It is worth mentioning that OCaml actually does support inheritance as part of its object system. That said, objects are an obscure part of the language, and inheritance even more so. At Jane Street, we almost never use objects and never use inheritance. We use standard functional programming techniques and code reviewers find that style more comprehensible. In particular, they can reason by following static properties of the code (module boundaries and functor applications) rather than dynamic properties (what class an object is).

This made me think of F#, which is inspired by OCaml. Will users of F# tend to not use any OO, just as in Jane Street Capital? Or, put in another way, will F# users tend to only be consumers of OO code (i.e., the .NET framework) and provide a "nice" OO-style API for client code, but "underneath the surface" focus entirerly on the functional part of F#?

Media: Wadler does a funny thing, in the very last minute of his talk (Faith, Evolution, and Programming Languages).