連想リストからassoc
再帰の(ry 勉強の為なので、一連のコードは既にあるメソッドなんかも気にせず実装してます。
#Ruby配列の配列で require "pp" def assoc(item,dict) if dict.empty? nil else if item == dict.first.first dict.first else dict.shift assoc(item,dict) end end end pp assoc("Two", [["Zero",0],["One",1],["Three",3],["Two",2]])
Scala版はタプルが要素になってるListを対象としたassocとしてみた。返り値のタプルの要素の型がどれでもいいような設定の仕方が、これでいいのかちょっと自信がない。というか、始め(T,T)ってしようとしたけど、最初のifのとこの(None,None)でerror type mismatch;だったのでこうしちゃったよ。
//Scala (Any,Any)でいいのだろうか? def assoc[T](item: T, list: List[(T,T)]): (Any,Any)={ if (list.isEmpty) None else if (item == list.head._1) list.head else assoc(item, list.tail) } println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2)))) //=>("Two",2)
//Scala パターンマッチ def assoc[T](item: T, list: List[(T,T)]): (Any,Any)= list match { case List() => (None,None) case head :: tail => if (item == head._1) head else assoc(item, tail) } println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2)))) //=>("Two",2)
10/13
上のコードで(Any,Any)を返り値としてて悶々としてたんですが、id:kmizushimaさんとymnkさんから教えてもらいました! ありがとうございます。
以下、kmizushimaさんより。
Scala版の方ですが、型エラーになる理由は、見つからなかったときに
(None, None)を返そうとしているからですね。見つからなかった場合は
Noneを、見つかった場合にはSome[(K, V)]を返すようにすべきだと思います。
以下、コード例。
def assoc[A, B](item: A, list: List[(A,B)]): Option[(A, B)] = list match { case Nil => None case head :: tail => if(item == head._1) Some(head) else assoc(item, tail) } println(assoc("Two",List(("Zero",0),("One",1),("Three",3),("Two",2)))) //=>Some("Two",2)
見つからないときに(None,None)ってしてたのは、見つかった時にタプルを返すので、それにあわせたような感じじゃないと返せないのかなと思ってこうしちゃったんですね。お恥ずかしい。
Option型に対する理解が一段進んだ感じ。ありがとうございました。