歌舞伎座.tech#9「異種プログラミング言語格闘勉強会」の資料
CC BY-SA 4.0
- 平和に生きたいので戦いません
どうせ負ける - 今回ほぼ唯一のML枠ですがMLっぽい話はしません
- 時間がないので一部説明なしの単語が登場します。あらかじめご了承ください。
- なかやん・ゆーき / ぺんぎん / もみあげ
- @pocketberserker / id:pocketberserker
- Microsoft MVP for
F#Visual Studio and Development Technologies (~ 2016/03/31)- カテゴリの変更が激しい…
- F#は前職で使っていたようだ?
- たぶんドワンゴ唯一のF#勢です
- マルチパラダイム
- .NET Framework向け
- http://fsharp.org/
- 2016/03/20時点の最新バージョンは 4.0
- パイプライン演算子
|>
がわりと有名らしい? - .NET系言語との連携を重視
- 他言語から呼び出されることも意識しつつ
NativePtr<'T>
という型もある
- F# 4.0の仕様(pdf)直リンク http://fsharp.org/specs/language-spec/4.0/FSharpSpec-4.0-latest.pdf
- Visual Studio Community Edition入れましょう
- F# のオプションにチェックいれないと入りません
- mono 4.2.2ならF#も一緒についてくる…はず
- 雑談場所 https://gitter.im/fsugjp/public
- 全国を見渡せばいくつかは仕事があるようだ
(日本のF#事情と世界のF#事情は異なるので、そのあたりを考慮してください)
- 細かいものから大きなものまで
- (たぶん)発表者の好みが混ざってます
// イミュータブル
let a = 1
// ミュータブル
let mutable b = 2
mutable
という長さが良い- 普段使わないやつに長いのキーワード
- Scalaの
var
はちょっと好きではない final
とかconst
は普段使いするには長すぎる(でも使う)
ジェネリック(ジェネリクス?)とかそのあたり。
// 代数的データ型
type Tree<'T> =
| Leaf of 'T
| Node of Node<'T> * 'T * Node<'T>
'T
が型パラメータ。'
が必要。- 地味だが、通常の型と区別がつきやすいので便利
"F# generic types do not support covariance or contravariance." ("The F# 4.0 Language Specification" 4.5.2 の Noteより抜粋)
C# よりも数が多い
// 引数のxはint option
let hoge x =
// このxはint
let x =
match x with
| Some x ->
// ここはint
x
| None -> 0
x + 1
- 同じ名前を付けたいときがあるのです
- わりと効く
- もちろんやりすぎは危険なので、publicなAPIには型を書くべき
- たまに気を利かせたつもりで
obj
に推論したりするので慢心ダメゼッタイ
|>
やモジュールを組み合わせることで推論できるパターンもあったりする
- オフサイドルール
let
とlet rec
- 基本は前方参照
- 前方で定義したものしか使えない
一部の数値型に単位をつけられる
[<Measure>] type g
[<Measure>] type kg
let g2kg (x : float<g>): float<kg> = x / 1000.0<g/kg>
- 単位はコンパイル時にerase
- パフォーマンスには影響しない
順番に配列したり結合可能な計算を記述するのに便利な構文を提供するための機能。 機能制限版マクロ…?
"The F# 4.0 Language Specification" の 6.3.10 に書かれた変換規則でもって変換を行う。
一番わかりやすい使われ方はモナド用構文(do記法やfor式みたいなやつ)。 あるいはasync awaitのようなやつ。
type OptionBuilder() =
member __.Bind(x, f) = Option.bind f x
member __.Return(x) = Some x
let option = OptionBuilder()
// これはNoneが返る
option {
let x = Some 1
let y = None
return x + y
}
とはいえ、ただ変換規則に沿ってメソッド呼び出しに展開しているだけなので別の挙動にもできる。
// https://github.com/BasisLib/Basis.Core/blob/f48ed463699ae0235aa58623d0f46c754a6f7326/Basis.Core/ComputationExpr.fs#L9
// 上記のビルダーを使えばC#っぽい挙動にもできる
option {
let x = Some 2
if x % 2 = 0 then return x * 2
return -1
}
// このコンピュテーション式はSome 4を返す
- 詳しい解説は以下(他力本願)
- 3.0以降:特定の組み合わせならオペレータを自分で定義できるので小ネタとしても使える?
"コンパイル時にコード生成に頼らずに型を生成する仕組み"です。 なんのこっちゃ。
色々ありすぎて困るが、大きな点で述べると
- higher kinded polymorphismがない
- varianceの関係でF#単独でHListを実装できない(たぶん)
- 網羅した形の日本語の資料, 書籍が少ない
- つらい
- type eraseではないCLIの仕様に寄り添う方針なのでつらいときがある
正直、資料や書籍の件以外は業務で使う分には問題にならないです、ええ。
愛憎入り混じっているので語れない。
OCaml + .NETが合体するとこうなるのか…と思いながら見てください。
let a = 1
let fizzbuzz n =
match (n % 3, n % 5) with
| 0, 0 -> "FizzBuzz"
| 0, _ -> "Fizz"
| _, 0 -> "Buzz"
| _ -> string n
let hoge x =
let rec inner acc x =
if x > 0 then
inner (acc + x) x - 1
else acc
inner 0 x
type Person = {
FirstName: string
LastName: string
}
let zd = {
FirstName = "ずん"
LastName = "どこ"
}
type IHoge =
abstract Foo: int -> string
[<AbstractClass>]
type AbstractHoge() =
abstract member Foo: int -> string
type Fuga() =
inherit AbstractHoge()
override __.Foo(x) = string x
interface IHoge with
member this.Foo(x) = this.Foo(x)