注意
ポエム、あるいは思想です。
私が完全に正しいとは思っていません。
そして、私は未だに Seq("foo", "bar", "baz") がどのようにして実体を List[String] として持っているのか理解していません。
という前提で話をグダグダしていきます。
主張
そんなに Seq が使いたいなら、こうすればいいのに!
val seq: Seq[String] = List("foo", "bar", "baz")
検索して見かけるもの
Scalaの記事でたまに見かけるものに
val seq = Seq("foo", "bar", "baz")
のようなものがあると思います。
あなたは初学者なので Seq が何か調べてみることもあるでしょう。
では、公式ドキュメントをあたりましょう。
次のうちのどれかか、全てを参照しました。
- https://www.scala-lang.org/api/2.12.x/scala/collection/Seq.html
- https://www.scala-lang.org/api/2.12.x/scala/collection/Seq$.html
- https://www.scala-lang.org/api/2.12.x/scala/collection/immutable/Seq.html
- https://www.scala-lang.org/api/2.12.x/scala/collection/immutable/Seq$.html
ここで驚くべきことに気付きます。
Seq は、なんと trait あるいは object なのです。
あなたはざっくりと、 trait がいわゆる interface のように使われると聞いていたのに、
interface をコンストラクタのように使っているのを見かけてしまったのです。
object は何かそういうことが出来るのかも知れませんが、しかし、 class Dog が interface Animal を実装した何かであるとしたら、 interface Animal が Animal である「何か」を作っているように見えるのです。
めちゃくちゃです。
さて、この疑問にあなたはさらに調べを進めていくこともあるでしょう。
object の方を読んでいたら
This object provides a set of operations to create Seq values. The current default implementation of a Seq is a List.
という記述を見つけるかも知れませんし、コマンドラインで
$ scala
と叩いて、REPLを立ち上げ、次のように Seq の実体がどうなっているか調べるかも知れません。
scala> Seq("foo", "bar", "baz")
val res0: Seq[String] = List("foo", "bar", "baz")
あるいは
で同様の記述を見つけるかも知れません。
ともあれ、 Seq は List であるようでした。
List について確認してみましょう。
- https://www.scala-lang.org/api/2.12.x/scala/collection/immutable/List.html
- https://www.scala-lang.org/api/2.12.x/scala/collection/immutable/List$.html
List は class です。
Seq の実体の正体に辿り着きました。
extends, with あたりを追って行けば、 List と Seq の関係が分かりますし、
の図を見ても関係性は直ぐに分かるでしょう。
いやいや、interface Animal が Animal である「何か」を作っているように見えるのは変わらないじゃないですか!
思うこと
val seq = Seq("foo", "bar", "baz")
初学者には厳しい
- なぜ「
Seqのコンストラクタで呼び出した実体がデフォルト実装でListである」という 暗黙知 を前提に記事を読まねばならないのか?- 初学者でなかったとしても Library のデフォルト実装を知っていようというのは筋肉な思想では?
- 「
traitってそのまま実体として呼び出せるのか?」と誤解させ得る example code は良くはないでしょう?
この感覚を持って欲しいのです。
さらに面白いことをしてみましょう。
厳密には違うでしょうが、 Seq() は Seq.apply() と同じであると聞いたことにしましょう。
REPLで遊んでみると?
scala> Seq.apply -- [E178] Type Error: ---------------------------------------------------------- 1 |Seq.apply |^^^^^^^^^ |missing argument list for method apply in class Delegate | | override def apply[A](elems: A*): CC[A] | | longer explanation available when compiling with `-explain` 1 error found
なんと class Delegate であると言うのです。もう分かんないですね。
そんなに Seq が使いたいなら、次のようにすれば、少し冗長ですが、実態に即しており、明確で誰も困らないものと思います。
val seq: Seq[String] = List("foo", "bar", "baz")
Tips
ちなみに以下の様に Seq よりも抽象的な trait でも同じように List が実体となっています。ワオ。
scala> Iterable("foo", "bar", "baz")
val res1: Iterable[String] = List(foo, bar, baz)
scala> Traversable("foo", "bar", "baz")
there was 1 deprecation warning; re-run with -deprecation for details
1 warning found
val res2: Iterable[String] = List(foo, bar, baz)