This week I had the please of attending GOTO Copenhagen - a 3 day developer conference covering a diverse range of topics.
Day 1
I started the day on the excellent Beyond the Microsoft Echo Chamber track taking in:
Mark demonstrated his open source project AutoFixture aimed at writing maintainable unit tests faster. Tobias described how Credit Suisse have been using F# to migrate large computations over from Excel, and created a minimal implementation live on stage. Glenn, a trilby hat fan, gave a flavour of Node.js, showing pre-built code running on Windows, Azure and Cloud9; socket.io looked particularly interesting.
Then I switched over to the Lean and Kanban case studies track for Jesper Boeg’s talk about Launching Kanban teams, and received a free Kanban book a the end, thanks!
Monday’s keynote was from Kasper Lund on the Dart programming language which I’d sum up as a programming language that runs in Chrome with “an unsurprising and familiar syntax” for Java and JavaScript programmers.
Day 2
The day started with a functional orientated keynote from Rich Hickey, author of Clojure, on The Value of Values.
I managed to catch the first 30 minutes of Simon Brown’s very interesting presentation Master-builder; the original generalising specialist? But had to nip out to do a video interview with fellow bowler hat wearer Werner Schuster on F# and FP which should be available on InfoQ in around a month or so.
After lunch I caught a great talk on dandelions Master-builders have rich conceptual models of software design from George Fairbanks.
Then it was my chance to talk about Functional Architecture:
Code samples:
Day 3
Another day, another Rich Hickey talk, this time on Writing Datomic in Clojure.
However most of my day was spent on the Programming with the Stars track which involved solving a minimal Minesweeper Kata in Java, functional Java, F# and C. Interestingly only the F# and C pairs were able to complete the task in the allotted hour.
I paired with Mark Seeman on the F# session. We were able to complete the computational version of the task with 15 minutes to spare, so even had time to start building a UI.
1: let compute (board : string) =
2: let options = System.StringSplitOptions.RemoveEmptyEntries
3: let board = board.Split([| "\n" |], options)
4: let count (x, y) =
5: [-1, -1; 0, -1; 1, -1;
6: -1, 0; 1, 0;
7: -1, 1; 0, 1; 1, 1]
8: |> List.map (fun (x', y') -> x + x', y + y')
9: |> List.filter (fun (x, y) ->
10: x >= 0 && x < board.[y].Length &&
11: y >= 0 && y < board.Length
12: )
13: |> List.sumBy (fun (x, y) ->
14: if board.[y].[x] = '*'
15: then 1 else 0
16: )
17: board |> Array.mapi (fun y line ->
18: line.ToCharArray() |> Array.mapi (fun x c ->
19: match c with
20: | '*' -> '*'
21: | '.' -> '0' + char (count(x, y))
22: | _ -> invalidArg "c" "Boo hiss!"
23: )
24: )
25: |> Array.map (fun chars -> System.String(chars))
26: |> Array.reduce (+)
27:
28: let input = "*...
29: ....
30: .*..
31: ...."
val compute : string -> System.String
Full name: Snippet.compute
val board : string
type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
Multiple items
val string : 'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
val options : System.StringSplitOptions
type: System.StringSplitOptions
inherits: System.Enum
inherits: System.ValueType
namespace System
type StringSplitOptions =
| None = 0
| RemoveEmptyEntries = 1
Full name: System.StringSplitOptions
type: System.StringSplitOptions
inherits: System.Enum
inherits: System.ValueType
field System.StringSplitOptions.RemoveEmptyEntries = 1
val board : string []
type: string []
implements: System.ICloneable
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.IStructuralComparable
implements: System.Collections.IStructuralEquatable
implements: System.Collections.Generic.IList<string>
implements: System.Collections.Generic.ICollection<string>
implements: seq<string>
implements: System.Collections.IEnumerable
inherits: System.Array
val count : (int * int -> int)
val x : int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
val y : int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of 'T * 'T list
with
interface System.Collections.IEnumerable
interface System.Collections.Generic.IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
end
Full name: Microsoft.FSharp.Collections.List<_>
type: List<'T>
implements: System.Collections.IStructuralEquatable
implements: System.IComparable<List<'T>>
implements: System.IComparable
implements: System.Collections.IStructuralComparable
implements: System.Collections.Generic.IEnumerable<'T>
implements: System.Collections.IEnumerable
val map : ('T -> 'U) -> 'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val x' : int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
val y' : int
type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType
val filter : ('T -> bool) -> 'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.filter
property System.Array.Length: int
val sumBy : ('T -> 'U) -> 'T list -> 'U (requires member ( + ) and member get_Zero)
Full name: Microsoft.FSharp.Collections.List.sumBy
module Array
from Microsoft.FSharp.Collections
val mapi : (int -> 'T -> 'U) -> 'T [] -> 'U []
Full name: Microsoft.FSharp.Collections.Array.mapi
val line : string
type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
Multiple overloads
System.String.ToCharArray() : char []
System.String.ToCharArray(startIndex: int, length: int) : char []
val c : char
type: char
implements: System.IComparable
implements: System.IConvertible
implements: System.IComparable<char>
implements: System.IEquatable<char>
inherits: System.ValueType
Multiple items
val char : 'T -> char (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.char
--------------------
type char = System.Char
Full name: Microsoft.FSharp.Core.char
type: char
implements: System.IComparable
implements: System.IConvertible
implements: System.IComparable<char>
implements: System.IEquatable<char>
inherits: System.ValueType
val invalidArg : string -> string -> 'T
Full name: Microsoft.FSharp.Core.Operators.invalidArg
val map : ('T -> 'U) -> 'T [] -> 'U []
Full name: Microsoft.FSharp.Collections.Array.map
val chars : char []
type: char []
implements: System.ICloneable
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.IStructuralComparable
implements: System.Collections.IStructuralEquatable
implements: System.Collections.Generic.IList<char>
implements: System.Collections.Generic.ICollection<char>
implements: seq<char>
implements: System.Collections.IEnumerable
inherits: System.Array
type String =
class
new : char -> string
new : char * int * int -> string
new : System.SByte -> string
new : System.SByte * int * int -> string
new : System.SByte * int * int * System.Text.Encoding -> string
new : char [] * int * int -> string
new : char [] -> string
new : char * int -> string
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : obj -> int
member CompareTo : string -> int
member Contains : string -> bool
member CopyTo : int * char [] * int * int -> unit
member EndsWith : string -> bool
member EndsWith : string * System.StringComparison -> bool
member EndsWith : string * bool * System.Globalization.CultureInfo -> bool
member Equals : obj -> bool
member Equals : string -> bool
member Equals : string * System.StringComparison -> bool
member GetEnumerator : unit -> System.CharEnumerator
member GetHashCode : unit -> int
member GetTypeCode : unit -> System.TypeCode
member IndexOf : char -> int
member IndexOf : string -> int
member IndexOf : char * int -> int
member IndexOf : string * int -> int
member IndexOf : string * System.StringComparison -> int
member IndexOf : char * int * int -> int
member IndexOf : string * int * int -> int
member IndexOf : string * int * System.StringComparison -> int
member IndexOf : string * int * int * System.StringComparison -> int
member IndexOfAny : char [] -> int
member IndexOfAny : char [] * int -> int
member IndexOfAny : char [] * int * int -> int
member Insert : int * string -> string
member IsNormalized : unit -> bool
member IsNormalized : System.Text.NormalizationForm -> bool
member LastIndexOf : char -> int
member LastIndexOf : string -> int
member LastIndexOf : char * int -> int
member LastIndexOf : string * int -> int
member LastIndexOf : string * System.StringComparison -> int
member LastIndexOf : char * int * int -> int
member LastIndexOf : string * int * int -> int
member LastIndexOf : string * int * System.StringComparison -> int
member LastIndexOf : string * int * int * System.StringComparison -> int
member LastIndexOfAny : char [] -> int
member LastIndexOfAny : char [] * int -> int
member LastIndexOfAny : char [] * int * int -> int
member Length : int
member Normalize : unit -> string
member Normalize : System.Text.NormalizationForm -> string
member PadLeft : int -> string
member PadLeft : int * char -> string
member PadRight : int -> string
member PadRight : int * char -> string
member Remove : int -> string
member Remove : int * int -> string
member Replace : char * char -> string
member Replace : string * string -> string
member Split : char [] -> string []
member Split : char [] * int -> string []
member Split : char [] * System.StringSplitOptions -> string []
member Split : string [] * System.StringSplitOptions -> string []
member Split : char [] * int * System.StringSplitOptions -> string []
member Split : string [] * int * System.StringSplitOptions -> string []
member StartsWith : string -> bool
member StartsWith : string * System.StringComparison -> bool
member StartsWith : string * bool * System.Globalization.CultureInfo -> bool
member Substring : int -> string
member Substring : int * int -> string
member ToCharArray : unit -> char []
member ToCharArray : int * int -> char []
member ToLower : unit -> string
member ToLower : System.Globalization.CultureInfo -> string
member ToLowerInvariant : unit -> string
member ToString : unit -> string
member ToString : System.IFormatProvider -> string
member ToUpper : unit -> string
member ToUpper : System.Globalization.CultureInfo -> string
member ToUpperInvariant : unit -> string
member Trim : unit -> string
member Trim : char [] -> string
member TrimEnd : char [] -> string
member TrimStart : char [] -> string
static val Empty : string
static member Compare : string * string -> int
static member Compare : string * string * bool -> int
static member Compare : string * string * System.StringComparison -> int
static member Compare : string * string * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
static member Compare : string * string * bool * System.Globalization.CultureInfo -> int
static member Compare : string * int * string * int * int -> int
static member Compare : string * int * string * int * int * bool -> int
static member Compare : string * int * string * int * int * System.StringComparison -> int
static member Compare : string * int * string * int * int * bool * System.Globalization.CultureInfo -> int
static member Compare : string * int * string * int * int * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
static member CompareOrdinal : string * string -> int
static member CompareOrdinal : string * int * string * int * int -> int
static member Concat : obj -> string
static member Concat : obj [] -> string
static member Concat<'T> : System.Collections.Generic.IEnumerable<'T> -> string
static member Concat : System.Collections.Generic.IEnumerable<string> -> string
static member Concat : string [] -> string
static member Concat : obj * obj -> string
static member Concat : string * string -> string
static member Concat : obj * obj * obj -> string
static member Concat : string * string * string -> string
static member Concat : obj * obj * obj * obj -> string
static member Concat : string * string * string * string -> string
static member Copy : string -> string
static member Equals : string * string -> bool
static member Equals : string * string * System.StringComparison -> bool
static member Format : string * obj -> string
static member Format : string * obj [] -> string
static member Format : string * obj * obj -> string
static member Format : System.IFormatProvider * string * obj [] -> string
static member Format : string * obj * obj * obj -> string
static member Intern : string -> string
static member IsInterned : string -> string
static member IsNullOrEmpty : string -> bool
static member IsNullOrWhiteSpace : string -> bool
static member Join : string * string [] -> string
static member Join : string * obj [] -> string
static member Join<'T> : string * System.Collections.Generic.IEnumerable<'T> -> string
static member Join : string * System.Collections.Generic.IEnumerable<string> -> string
static member Join : string * string [] * int * int -> string
end
Full name: System.String
type: System.String
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
val reduce : ('T -> 'T -> 'T) -> 'T [] -> 'T
Full name: Microsoft.FSharp.Collections.Array.reduce
val input : string
Full name: Snippet.input
type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>
No surprises then that according to the ICFP:
F# is the programming language of choice for discriminating hackers
For the C session I paired with John Nolan. Again we were able to complete the computational task, this time with only 30 seconds to spare, and it certainly wasn’t pretty, but still a lot of fun!
Since the conference I’ve knocked up an Erlang version: http://pastebin.com/s9mChuPp
Plus another F# version that fits nicely in a Tweet (140 characters): http://fssnip.net/ce
s|>Array2D.mapi(fun x y->function '*'->'*'|_->'0'+char([for i in 0..8->i%3-1,i/3-1].Count(fun(x,y)->x>=0&&x=0&&y<m&&s.[x,y]='*')))
End of day 3
The last talk of the day for me was Nat Pryce’s excellent Stop Refactoring! talk on the Iconoclasts track:
An iconoclast is someone who performs iconoclasm — destruction of religious symbols, or, by extension, established dogma or conventions.
Nat retold his observations of refactoring ping-pong:
Refactor one way, then another. then back again
The main message was that “code doesn’t need to be perfect only habitable” and::
The imperfection of our code is really motion blur, as the state of the code is simply a snapshot as it evolves
Day after
I really enjoyed the conference, saw some inspiring talks, and met some really interesting people, and would recommend Goto Copenhagen to anyone interested in software development. Read more about the conference and more specifically Concurrent Programming using the Disruptor over on Trisha’s blog.
Finally it appears to me that people are not wearing enough hats.