fluent feature in f#

23
F# ののの Fluent Feature in F# by ののの のののの ののののの 。。

Upload: igeta

Post on 25-Jun-2015

2.224 views

Category:

Documents


0 download

DESCRIPTION

from OCaml Meeting 2010 in Nagoya

TRANSCRIPT

Page 1: Fluent Feature in F#

F# の流技Fluent Feature in F#

by いげ太

あいさつ。自己紹介。

Page 2: Fluent Feature in F#

本田△

流技といえば本田。無回転シュート。空気の流れを利用。大活躍!ネットでよくこんなのを見た。「本田△」は前へ前へ攻めていく感じ?じゃなく、本田△⇒本田三角形⇒本田さんかっけー⇒本田さんカッコイイ。

Page 3: Fluent Feature in F#

OCaml△

ていうか、今日は OCaml Meeting なわけで。OCaml さんかっけー。って言いたかったけど、僕は Windows しか知らないので。

Page 4: Fluent Feature in F#

F# △

似た言語である F# について話したい。 F# は、かんたんには OCaml.NET です。ていうか。△似合わない? サッカーならいい。アゲアゲで、敵陣に攻めてる感じ。プログラミング言語で、上って? ソース コードの上の方? それ後ろ向きじゃん。

Page 5: Fluent Feature in F#

前向きにいきましょう。矢印は未来を指してないと。F# には横向きの三角、というか、矢印がよく似合います。でもこれ、縦書き文字で無理やり横向きの三角を出してますので。

F#

Page 6: Fluent Feature in F#

F# |>

こうしましょう。パイプと大なりであらわす。この横向きの矢印は、 F# ではパイプライン演算子と呼ばれます。パイプライン演算子は、ライブラリ標準の演算子だったりします。

Page 7: Fluent Feature in F#

パイプライン演算子 |>

h (g (f x))↓

x |> f |> g |> h

ネストいらずって素敵やん!?

関数適用のネストをなくして見やすくする演算子。補助的な演算子。前から順番に、 x を f に適用して、その返り値を g に適用して、またその返り値を h に適用して、その結果を得る。わかりやすい!

Page 8: Fluent Feature in F#

パイプライン演算子?

let (|>) x f = f x

let wup n = 2 * nlet ans = 2 |> wup |> wup |> wup

// val ans : int = 16

(|>) は、前向きなパイプライン演算子、前方パイプ演算子。定義はこんな風になっている。ちょっとした例も。ダブルアップで倍々ゲーム。でもさ、若干だけど、重くなるんじゃない? 無駄じゃない、こんなの?

Page 9: Fluent Feature in F#

パイプライン演算子!

let inline (|>) x f = f x

let wup n = 2 * nlet ans = 2 |> wup |> wup |> wup// let ans = wup (wup (wup 2))

// val ans : int = 16

(|>) は、実際にはインライン関数(演算子)として定義されています。インライン展開されるので実行時のコストはゼロ。気兼ねなく、存分に使ってください。乱用バッチコイ。

Page 10: Fluent Feature in F#

後ろから前から

h @@ g @@ f @@ x

h (g (f x))

x |> f |> g |> h

関数型の語順

でもさ、関数型コードとの親和性で言えば @@ の方がいいんでない?

Page 11: Fluent Feature in F#

F# は .NET 言語であり、当然 OOP の機能を備える。.NET 使いも納得の思考の流れでコードが記述できる。

.NET といえばオブジェクト指向ですよ

h @@ g @@ f @@ x

x.F().G().H()

x |> f |> g |> h OOP の語順

Page 12: Fluent Feature in F#

ところで、 F# Team の一人である Brian McNamara が、stackoverflow のとあるスレッドでこんなことを書いていました。要は、ざっくり言うと、前方パイプ演算子は文化だ、と。

前方パイプ演算子は文化だ

Brian McNamara writes,

“I think (|>) is an important operator in the F# ‘culture’.”

http://stackoverflow.com/questions/1457140/

Page 13: Fluent Feature in F#

文化ですってよ。

One more thingOne more thing...

<censored>

Page 14: Fluent Feature in F#

ドット記法の語順とあわせ打っただけをもって「文化」と言っているわけじゃあない。

<censored>

だけじゃないOne more thing...

だけじゃない!!

<censored>

Page 15: Fluent Feature in F#

F# 「 OCaml と違うんです」

(* OCaml *)let n = 2 + 3 (* 5 *)let m = 2.0 +. 3.0 (* 5.0 *)

// F#let n = 2 + 3   // 5let m = 2.0 + 3.0   // 5.0

たとえば、 .NET には演算子オーバーロードがある。型推論の完全性を重んじる OCaml とは一線を画す。

Page 16: Fluent Feature in F#

オーバーロードと型推論

let func1 x = System.Console.WriteLine(x) // error FS0041 x + 1

let func2 (x: int) = System.Console.WriteLine(x) x + 1let func3 x = let y = x + 1 System.Console.WriteLine(x) ylet func4 x = printfn "%A" x x + 1

まあ割と型推論と相性が悪いのですけどもー。型推論ってば、評価時の型環境すべてをひっくるめて見てくれる。でも、オーバーロード解決は、その場その場で行われる。

Page 17: Fluent Feature in F#

F# 「 .NET ですから」

• OCaml は Structural Subtyping• OCaml には Row Polymorphism もある• F# は Nominal Subtyping• .NET 的に考えて Nominal でなきゃマズ

⇒ F# の型推論は残念!?

で、オブジェクト指向の方向性としても、こんな風に違うわけで。ちょっと難しいので突っ込んで話はしませんが。

Page 18: Fluent Feature in F#

デモ> String.length "hoge";;val it : int = 4> "hoge".Length;;val it : int = 4> String.length;;val it : (string -> int) = <fun:it@3>> (fun s -> s.Length);;

(fun s -> s.Length);; ----------^^^^^^^^

stdin(4,11): error FS0072: このプログラムの場所の前方にある情報に基づく不確定の型のオブジェクトに対する参照です。場合によっては、オブジェクトの型を制約する型の注釈がこのプログラムの場所の前に必要です。この操作で参照が解決される可能性があります。> (fun (s: string) -> s.Length);;val it : string -> int = <fun:clo@5>

とりあえず、 OCaml 的に考えて、どんなふうに残念かってーのをデモで見ます。ドット記法で書かれたオブジェクトの型は推論されない!型注釈に頼らざるを得ない。

Page 19: Fluent Feature in F#

デモ> let intLength n =- (fun (s: string) -> s.Length)- ( (fun n -> n.ToString()) n );;

val intLength : 'a -> int

> let intLength n =- (fun (s: string) -> s.Length)- ( (fun (n: int) -> n.ToString()) n );;

val intLength : int -> int

> let intLength (n: int) =- n |> (fun n -> n.ToString()) |> (fun s -> s.Length);;

val intLength : int -> int

ちょっと意図的な例。それぞれの引数に型注釈付けるのは煩雑極まりない。なんとかならない? それまでに型が決まればいい。 F# の型決定は左から右。なので、前方パイプ演算子を使えば、残念さをすこしはカバーできるかも!?

Page 20: Fluent Feature in F#

まとめ

> F#- |> 関数型ベース- |> .NET 言語ですが何か- |> OOP は必須です- |> Nominal だし型注釈を免れない- |> 型推論を最大限活かしたい- ;;

val it : culture = だまって前方パイプ書けよ

Page 21: Fluent Feature in F#

More Feature

• 単位系 → 数値に単位を付けて計算

• アクティブ パターン → パターンとして使用できる関数

• オブジェクト式 → 無名クラス

• コンピュテーション式 → モナド

• イベント ドリブン → リアクティブに記述可能

• 非同期実行 → 非同期ワークフロー、アクター

他にもおもしろいのいっぱいあるよー。

Page 22: Fluent Feature in F#

Reserved as Keywordsfor future expansion

atomic break checked component

const constraint constructor

continue

eager event external fixed

functor include method mixin

object parallel process protected

pure sealed tailcall trait

virtual volatile

http://msdn.microsoft.com/en-us/library/dd233249.aspx

わくわくどきどきの将来の機能拡張のための予約語。

Page 23: Fluent Feature in F#

F#F is for Fun!

ありがとうございました。