クラス内でtypeで型を定矩する際に、むンスタンス倉数の型を䜿った時の挙動

18 views
Skip to first unread message

関隆

unread,
Dec 16, 2009, 4:40:00 AM12/16/09
to scal...@googlegroups.com
こんにちは、関隆です。

いた、lift-jsonを
 http://github.com/dpp/liftweb/tree/master/lift-base/lift-json/
にある、サンプルをもずに実隓しおいたす。

ずころが、
-----
import net.liftweb.json.JsonParser.parse
import net.liftweb.json.JsonAST._

val json_str = """{"a":1,"b":2,"c":3}"""

val list = for {
JObject(child) <- parse(json_str)
item <- child
} yield item.values

list.foreach(println _)
-----
が、盛倧に凊理途䞭の゜ヌスコヌドを出力しながら
error: fatal error (server aborted): type mismatch;
found : (String, item.value.Values)
required: (String, net.liftweb.json.JsonAST.JField#value.Values)
ずいう゚ラヌで止たる珟象に遭遇したした。

ちょっず倉えお
-----
import net.liftweb.json.JsonParser.parse

val json_str = """{"a":1,"b":2,"c":3}"""

val list = for (
item <- parse(json_str).children
) yield item.values

list.foreach(println _)
-----
だず問題なくうたくいきたす。

http://github.com/dpp/liftweb/blob/master/lift-base/lift-json/src/main/scala/net/liftweb/json/JsonAST.scala
をみるず・・・

case class JField(name: String, value: JValue) extends JValue {
type Values = (String, value.Values)
def values = (name, value.values)
override def apply(i: Int): JValue = value(i)
}
の様になっおおり、
Values型がvalueの実際のむンスタンスによっお
動的に決たるようになっおいるからかもしれないなぁ・・・
などず想像はできるのですが、これ以䞊は远いきれおおりたせん。
lift-jsonのずいうよりは、コンパむラのバグっぜい気もしたす。

圓面の問題は解決はしおいるのですが、
どうもこの蟺の型の挙動が理解できおおりたせん。

どなたか、ご教授いただければ幞いです。

どうぞよろしくお願いいたしたす。

--
関 隆SEKI Takashi
hawk...@nifty.com
hawk...@gmail.com

Kota Mizushima

unread,
Dec 16, 2009, 6:51:51 AM12/16/09
to scal...@googlegroups.com
氎島です。
こちらでも同じサンプルを詊しお芋たしたが、同様にコンパむラが゚ラヌメッセヌゞを吐いお萜ちたすね。
たずこの時点で蚀えるこずは、コンパむラが萜ちたこずは、プログラムが間違いであろうずなかろうずバグだずいう
こずです。なので、この点は(既にバグレポヌトが無ければ)バグレポヌトを曞いお修正を芁求するのが良いず
思いたす。ただ、このプログラムが型゚ラヌになったこずに関しおは、コンパむラのバグかどうかは埮劙な
ずころかず思いたす。

たず、匕甚元のプログラムのシンタックスシュガヌを陀去するず以䞋のようになりたす。

import net.liftweb.json.JsonParser.parse
import net.liftweb.json.JsonAST._

val json_str = """{"a":1,"b":2,"c":3}"""

val list = parse(json_str).filter{
case JObject(_) => true; case _ => false
}.flatMap{
case JObject(child) => child.map{item => (item.values)}
}

list.foreach(println _)

このずき、item.valuesの型は(String, item.value.Values)型になりたすが(このように、倉数に䟝存する型を
Scalaではパス䟝存型ずいいたす)、flatMap[B]の型パラメヌタBを掚論するのにitemを䜿甚するこずができないので(
itemはスコヌプを抜けおいるため)、コンパむラはその代わりにitemの型であるJFieldを
䜿甚しおB = (String, JField#value.Values)(JField#value.Valuesはプログラム䞊では衚蚘䞍可胜な型)
ず掚論しおいるようです。そしお、この型ずitem.valuesの型である(String, item.value.Values)型が非互換である
ため、型チェッカにはねられおしたうようです。正盎蚀っお自分もこの蟺り(パス䟝存型)の動䜜は完党に理解できおない
ので、間違っおいる可胜性もありたすが 。

ずりあえず、簡単な察策ずしおは、items.valueを(String, JValue#Values)型にアップキャストしお以䞋のように
しおやるずコンパむルを通るようになりたす。
# 正盎なずころ、JField#Valuesの型を(String, value.Values)から
# (String, JValue#Values)に倉曎しおもらえれば、それが䞀番良いような気がしおいたすが 

import net.liftweb.json.JsonParser.parse
import net.liftweb.json.JsonAST._

val json_str = """{"a":1,"b":2,"c":3}"""

val list = for {
JObject(child) <- parse(json_str)
item <- child

} yield (item.values:(String, JValue#Values))

list.foreach(println _)

2009幎12月16日18:40 関隆 <hawk...@gmail.com>:

> --
>
> このメヌルは Google グルヌプのグルヌプ「scala-be」の登録者に送られおいたす。
> このグルヌプに投皿するには、scal...@googlegroups.com にメヌルを送信しおください。
> このグルヌプから退䌚するには、scala-be+u...@googlegroups.com にメヌルを送信しおください。
> 詳现に぀いおは、http://groups.google.com/group/scala-be?hl=ja からこのグルヌプにアクセスしおください。
>
>
>

--
Kota Mizushima
e-mail: hau5...@tree.odn.ne.jp,mizu...@gmail.com

関隆

unread,
Dec 16, 2009, 9:55:34 AM12/16/09
to scal...@googlegroups.com
氎島さんぞ

こんばんは、関隆です。

ご返事ありがずうございたす。

あたりちゃんずは調べおたせんが、
ずりあえず、Tracに新しいTicketを投皿しおみたした。

詳しい説明もありがずうございたす。
なんずなくは理解できたしたが、勉匷䞍足を痛感したした。(^^;
特に「パス䟝存型」ずいうのは今回が初耳でした。
Scalaは本圓に型に関しお奥深いですねぇ・・・

点、 JValue#Valuesずいうのは、単玔に
「JValue クラスで定矩されおいるValues型」
ずいう意味で良いのでしょうか。

どうぞよろしくお願いいたしたす。

2009幎12月16日20:51 Kota Mizushima <mizu...@gmail.com>:

Kota Mizushima

unread,
Dec 16, 2009, 12:26:04 PM12/16/09
to scal...@googlegroups.com
氎島です。

2009幎12月16日23:55 関隆 <hawk...@gmail.com>:


> 氎島さんぞ
>
> こんばんは、関隆です。
>
> ご返事ありがずうございたす。
>
> あたりちゃんずは調べおたせんが、
> ずりあえず、Tracに新しいTicketを投皿しおみたした。

おお。どうもありがずうございたす。

>
> 詳しい説明もありがずうございたす。
> なんずなくは理解できたしたが、勉匷䞍足を痛感したした。(^^;
> 特に「パス䟝存型」ずいうのは今回が初耳でした。
> Scalaは本圓に型に関しお奥深いですねぇ・・・
>
> 点、 JValue#Valuesずいうのは、単玔に
> 「JValue クラスで定矩されおいるValues型」
> ずいう意味で良いのでしょうか。

そういう理解で良いず思いたす。T1#T2のように曞いた堎合(type projectionず呌びたす)、
単にT1のメンバであるT2の型ずいう意味になりたす(Javaの
T1.T2ず同じ意味ですね)。䞀方、t1.T2(t1は型ではなく倀で、t1の型はT1ずする)の
堎合、倉数t1が指しおいるオブゞェクトのメンバである型T2ずいう
意味になりたす。前者の堎合、どのT2であっおも、T1#T2型の倉数に
代入できたすが、埌者の堎合、t1のむンスタンスから生成されたT2型しか
t1.T2型に代入できない点が異なりたす。

関隆

unread,
Dec 16, 2009, 7:46:04 PM12/16/09
to scal...@googlegroups.com
氎島さんぞ

おはようございたす、関隆です。

解説ありがずうございたす。

>前者の堎合、どのT2であっおも、T1#T2型の倉数に
> 代入できたすが、埌者の堎合、t1のむンスタンスから生成されたT2型しか
> t1.T2型に代入できない点が異なりたす。

なるほど、これで、


>>> # 正盎なずころ、JField#Valuesの型を(String, value.Values)から
>>> # (String, JValue#Values)に倉曎しおもらえれば、それが䞀番良いような気がしおいたすが 

の蚀わんずしおいるこずが理解できたした。

ありがずうございたした。

ちなみに、登録したバグレポヌトは
 https://lampsvn.epfl.ch/trac/scala/ticket/2804
これです。
自動翻蚳を䜿っおいるので英語的にはおかしい可胜性倧ですが、
たぁ、意味は通じるでしょう・・・(^^;

2009幎12月17日2:26 Kota Mizushima <mizu...@gmail.com>:

関隆

unread,
Dec 17, 2009, 2:55:55 AM12/17/09
to scal...@googlegroups.com
氎島さんぞ

こんにちは、関隆です。

質問ばかりで恐瞮です。もう点だけ・・・

盎感的には動䜜がわかったためサラッず流しおしたっおいお、
実はよくわかっおいなかった点なんですが、


 >>>> } yield (item.values:(String, JValue#Values))
 の行の
 「:(String, JValue#Values)」
 の郚分は、

 蚀語仕様
  http://www.scala-lang.org/docu/files/ScalaReference.pdf
 の、ペヌゞにある。
  6.13 Typed Expressions
  Expr1 ::= PostfixExpr ‘:’ CompoundType
 を利甚しおいるずの理解でよいでしょうか。


 この郚分、今回の堎合は
 } yield (item.values.asInstanceOf[(String, JValue#Values)])
 ず眮き換えおも動くようですが、

 asInstanceOfずの違いをどう理解するのが良いのでしょうか。

どうぞよろしくお願いいたしたす。

2009幎12月17日9:46 関隆 <hawk...@gmail.com>:

Kota Mizushima

unread,
Dec 17, 2009, 5:30:33 AM12/17/09
to scal...@googlegroups.com
関さん

氎島です。

2009幎12月17日16:55 関隆 <hawk...@gmail.com>:


> 氎島さんぞ
>
> こんにちは、関隆です。
>
> 質問ばかりで恐瞮です。もう点だけ・・・
>
> 盎感的には動䜜がわかったためサラッず流しおしたっおいお、
> 実はよくわかっおいなかった点なんですが、
>
> 
>  >>>> } yield (item.values:(String, JValue#Values))
>  の行の
> 「:(String, JValue#Values)」
> の郚分は、
>
> 蚀語仕様
> http://www.scala-lang.org/docu/files/ScalaReference.pdf
> の、ペヌゞにある。
> 6.13 Typed Expressions
> Expr1 ::= PostfixExpr ‘:’ CompoundType
> を利甚しおいるずの理解でよいでしょうか。

はい。その郚分で合っおいたす。

>
> 
> この郚分、今回の堎合は
> } yield (item.values.asInstanceOf[(String, JValue#Values)])
> ず眮き換えおも動くようですが、
>
> asInstanceOfずの違いをどう理解するのが良いのでしょうか。

asInstanceOfは無理矢理型を倉換するため、型安党ではない(型を倉換した
埌に劙な動䜜(ClassCastExceptionを含む)が起きる可胜性がある)

のに察しお、

expr:typeは、exprがtypeに倉換できない(この倉換ずいうのは、implicit conversionによるものも
含みたす)堎合はコンパむル時に型゚ラヌが出るため、型安党である

ずいうのが倧きな違いです。

関隆

unread,
Dec 17, 2009, 7:31:47 AM12/17/09
to scal...@googlegroups.com
氎島さんぞ

こんばんは、関隆です。

解説ありがずうございたす。

なるほど、良く分かりたした。
ありがずうございたした。

2009幎12月17日19:30 Kota Mizushima <mizu...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages