3 people like it.

Erik Lippert's Comma Quibbling

An old solution of mine to Erik Lippert's Comma Quibbling challenge. I really like this snippet because it shows that with F# we can hack elegant but also fast code.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
// http://blogs.msdn.com/b/ericlippert/archive/2009/04/15/comma-quibbling.aspx

#time
#r "FSharp.PowerPack.dll"
open System
open System.Text


let format (words : seq<string>) =
    let sb (value : string) = new StringBuilder(value)
    let (<+>) (first : StringBuilder) (second : string) = first.Append(second)
    let rec format (words : LazyList<string>) acc =
        match words with
        | LazyList.Nil -> sb ""
        | LazyList.Cons(first, LazyList.Nil) -> sb first
        | LazyList.Cons(first, LazyList.Cons(second, LazyList.Nil)) -> acc <+> first <+> " and " <+> second
        | LazyList.Cons(first, rest) ->  acc <+> first <+> ", " |> format rest 
          
    let listOfWords = LazyList.ofSeq words  
    sprintf "{%s}" <| (format listOfWords (sb "")).ToString() 

["ABC"; "DEF"; "G"; "H" ] |> format
["ABC"; "DEF" ] |> format 
["ABC"] |> format
[""] |> format
{1..10000} |> Seq.map string |> format 
namespace System
namespace System.Text
val format : words:seq<string> -> string

Full name: Script.format
val words : seq<string>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val sb : (string -> StringBuilder)
val value : string
Multiple items
type StringBuilder =
  new : unit -> StringBuilder + 5 overloads
  member Append : value:string -> StringBuilder + 18 overloads
  member AppendFormat : format:string * arg0:obj -> StringBuilder + 4 overloads
  member AppendLine : unit -> StringBuilder + 1 overload
  member Capacity : int with get, set
  member Chars : int -> char with get, set
  member Clear : unit -> StringBuilder
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EnsureCapacity : capacity:int -> int
  member Equals : sb:StringBuilder -> bool
  ...

Full name: System.Text.StringBuilder

--------------------
StringBuilder() : unit
StringBuilder(capacity: int) : unit
StringBuilder(value: string) : unit
StringBuilder(value: string, capacity: int) : unit
StringBuilder(capacity: int, maxCapacity: int) : unit
StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
val first : StringBuilder
val second : string
StringBuilder.Append(value: char []) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: obj) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint16) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: decimal) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int) : StringBuilder
   (+0 other overloads)
val format : ('a -> 'b -> 'c)
val words : 'a
val acc : 'b
val listOfWords : obj
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
module Seq

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/6F
Posted:13 years ago
Author:Nick Palladinos
Tags: lazylist