わんくまでF#に敬意を表しつつセッション発表してきました、というお話

わんくま同盟

わんくま同盟名古屋勉強会 #16で発表してきました。タキシードで。

用意するモノ

  • F#に対する敬意
  • タキシード
  • やけくそな気持ち

用意しないモノ

  • 平常心

F#で関数型言語に触れてみよう

タキシード着てF#のコーディングする人間がいても別に驚かないけど、
まさか自分がそうなるとは思ってませんでした。

発表中に作った(コピペした)コードがこちらです。

let verboseLevel = ref 0
let warningLevel = ref 0
let isQuiet = ref false
let outputfile = ref "default.out"

let parse_args args =
  let specs = [
    ("-v", "--Verbose", None, Some(fun x -> verboseLevel := Int32.Parse(x)) );
    ("-w", "--Warn", None, Some(fun x -> warningLevel := Int32.Parse(x)) );
    ("-q", "--Quiet", Some(fun _ -> isQuiet := true), None );
    ("-o", "--Output", None, Some(fun x -> outputfile := x) );
  ]
  let rec parse files xs = 
    match xs with
    | [] -> files
    | hd :: tl ->
      let a = List.tryFind (fun (shop, op, _, _) -> shop = hd || op = hd) specs
      match a with
      | Some (_, _, Some(f), None) -> f (); parse files tl
      | Some (_, _, None, Some(f)) -> f tl.Head; parse files tl.Tail
      | Some (_, _, _, _) -> failwith "oops!"
      | None -> parse (files @ [hd]) tl 

  Array.toList args |> List.tail |> parse []

そんで、このコードを見て[twitter:@mzp]さんが、「このコードはアカン!粛正リファクタリングしる!」と!ライトニングトーク粛正リファクタリングしていただいたのがこちらです。

let verboseLevel = ref 0
let warningLevel = ref 0
let isQuiet = ref false
let outputfile = ref "default.out"

type act =  Noarg of (unit -> unit)
          | Onearg of (string -> unit)

let parse_args args =
  let specs = [
    ("--Verbose", "-v", Onearg(fun x -> verboseLevel := Int32.Parse(x)));
    ( "--Warn","-w", Onearg(fun x -> warningLevel := Int32.Parse(x)));
    ("--Quiet", "-q", Noarg(fun _ -> isQuiet := true));
    ("--Output", "-o", Onearg(fun x -> outputfile := x));
  ]
  
  let rec parse files  =
    function
    | [] -> files
    | hd :: tl ->
      let a = List.tryFind (fun (op, shop, _) -> hd = op || hd = shop) specs
      match a with
      | Some (_, _, Noarg(f)) -> f (); parse files tl
      | Some (_, _, Onearg(f)) -> f tl.Head; parse files tl.Tail
      | None -> parse (files @ [hd]) tl 

  args
  |> Array.toList
  |> List.tail
  |> parse []

判別共用体を使うアイデアは思いつきませんでした。こっちの方がスッキリしますね。

個人的には面白かったです。