Scala の CanBuildFrom などについて

implicit conversionとかCanBuildFrom関係ないことも混ざってるけど気にするな。自分が入れたいものを入れただけです(・ω・`)ほんとtwitterやってるだけで勉強になりますね
2
kmizu @kmizu

あと、厳密に語るなら、構文、型システム、(実行時の)意味論、に分けて論じる必要がある。Scalaに関して言うと、構文と(実行時の)意味論は割と単純。型システムは「複雑」だけど、その「複雑さ」に出会うのは、主にライブラリ設計者であって、ふつーのユーザは型システムの暗黒面に

2011-07-03 11:30:43
kmizu @kmizu

触れなくてもいいように、大体うまく設計されている。 #scala

2011-07-03 11:30:57
kmizu @kmizu

Stringを要素に持つ任意のコレクションにgrepを適用できるようにする - あるいはScalaの暗黒面について http://bit.ly/kGEbdK のエントリについて、補足を末尾に書いた。 #scala

2011-07-03 11:53:11
kmizu @kmizu

このエントリで、Scalaの暗黒面に触れざるを得なかったのは、「戻り値同型の原則」を遵守するためであって、それを放り投げていいなら、別に難しくないよー、という補足です。 #scala

2011-07-03 11:53:58
kmizu @kmizu

@nobsun まず、概念として複雑になります。利用者側はそれほど複雑なことを知らなくてもいいですが、汎用ライブラリ(目的が限定されているものは含まない、という意味です)の設計者は型システムに関する複雑な概念をある程度知っておく必要があります。 #scala

2011-07-03 12:06:14
kmizu @kmizu

@lyrical_logical 私自身は難しいとは特に感じてませんです。ただ、 CanBuildFrom なんかよくわからない、と思っている方は結構居られそうなので、なんか書きました。

2011-07-03 13:33:17
kmizu @kmizu

CanBuildFromを次のポストで140文字以内で説明してみるテスト。ただし、型パラメータ名From, Elem, Toはあらかじめ知っているものとする。 #scala

2011-07-03 13:52:11
kmizu @kmizu

From型のコレクションから「Elemを要素型に持つTo型のコレクションを生成するためのビルダ」を生成するためのファクトリオブジェクト。以上。具体例が無ければ140文字以内でかけた。 #scala

2011-07-03 13:55:52
kmizu @kmizu

具体例。 CanBuildFrom[List[Int], String, List[String]] 。List[Int] から、「List[String]を生成するためのビルダ」を生成するファクトリ。具体的なインスタンスは「勝手に湧いてくる」ので知らんでもいい #scala

2011-07-03 14:01:18
kmizu @kmizu

微妙な例。 CanBuildFrom[Map[Int, Int], Int, Map[Int, Int]]。 こんな型のインスタンスは勝手に湧いてきません(そういう風に作れるけど)。 #scala

2011-07-03 14:05:14
kmizu @kmizu

CanBuildFrom[Map[Int, Int], Int, Iterable[Int]] 。これはOK。

2011-07-03 14:06:30
kmizu @kmizu

CanBuildFrom[Set[Int], String, Set[String]]。こういうのもOK。 #scala

2011-07-03 14:06:39
kmizu @kmizu

CanBuildFrom[List[String], String, Set[String]] 。こういうのもデフォルトではだめ(自作すればいけるけど)。 #scala

2011-07-03 14:13:56
akihiro @akihiro4chawon

// breakOutで適切なビルダを解決(後からtoSetよりパフォーマンス的にうれしい) import collection.breakOut val s: Set[String] = List("foo", "bar").map(identity)(breakOut)

2011-07-03 14:20:03
akihiro @akihiro4chawon

identity の部分は、実際には何か有意義な変換をするコードを書くものだということで。

2011-07-03 14:20:59
kmizu @kmizu

結局、どういうときにCanBuildFromのインスタンスが「湧いてくる」かというと: "CanBuildFrom[C[A], B, D[B]] where D[B] >: C[A] (C, Dは任意のジェネリックなコレクション型)" が成り立つとき(例外あり)。 #scala

2011-07-03 14:22:14
kmizu @kmizu

これはもちろん言語仕様で定めているわけではなく、そうなるようにコレクションライブラリが設計されているから。 #scala

2011-07-03 14:22:38
akihiro @akihiro4chawon

結構昔に、kaitenn さんが breakOut の使い方について何かコメントされていたはず。たしか、stack overflow の引用だったかな。

2011-07-03 14:22:42
kmizu @kmizu

http://bit.ly/l7vsc4 でミス。"CanBuildFrom[C[A], B, D[B]] where D[B] >: C[B] (C, Dは任意のジェネリックなコレクション型)" が正しい。 #scala

2011-07-03 14:24:17
++C++; // 管理人: 岩永 @ufcpp

ScalaのトレイトとかRubyのmix-inモジュールよりも、C# の拡張メソッド(実体はただのstaticメソッド)が好きな自分はstaticおじさんと呼ばれてしまうのだろうか。

2011-07-03 15:46:34
++C++; // 管理人: 岩永 @ufcpp

何でもかんでもstaticなのと同程度に、全メソッドがvirtualなのも嫌。

2011-07-03 16:08:05
++C++; // 管理人: 岩永 @ufcpp

OOP(継承、多態)とstaticは相互排他じゃないという説明がしたいのだけど、相変わらず「理系前提」脳が働いてしまっており、「整数はユークリッド聖域」=インターフェイス、「ユークリッド聖域には互除法が使える」=こういうのはstaticでOKとかいう例しか思い浮かばない。

2011-07-03 16:34:19
kmizu @kmizu

@ufcpp C# の拡張メソッドと対比するのに適切な機能は、 Scala だと implicit conversion、 Rubyならオープンクラスな気がします。 #scalajp

2011-07-03 17:29:25
がくぞ @gakuzzzz

単に「戻り値同型の原則 」だけを実現するならCanBuildFromなんて要らなくて、実装メソッドの戻り値型を自分自身の型で宣言すればいい。Javaでも5以降それで実現できる。でもそうするとmap等の実装を各クラスに書く必要がでてきてDRY原則に反する。(続く) #scala

2011-07-03 18:10:49