Scala 括号语义 [英] Scala parenthesis semantics

查看:31
本文介绍了Scala 括号语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在向 MAP 附加值时,为什么 Scala 需要额外的括号块来使该语句起作用?

When appending values to a MAP, why does Scala require the additional parenthesis-block to make this statement work?

不编译:

vmap += (item.getName(), item.getString()) // compiler output: "found: String"

但是,这确实可以编译:

However, this Does compile:

vmap += ((item.getName(), item.getString())) // note the second set of enclosures

TIA

vmap 定义为

val vmap = new mutable.HashMap[String, String]()

尾声:在进行此编辑时,有一些帖子详细说明了两种可能的解释,这两种解释似乎都包含对他们来说真实的元素.哪一个实际上是正确的?我不能肯定地说......我只是一个仍在学习语言的人.话虽如此,我已经根据感觉更改了答案选择,即一个答案(至少在某种程度上)包含在另一个答案中 - 所以我选择了更大的图片,因为我认为它将为寻求答案的其他人提供更广泛的含义.具有讽刺意味的是,我试图更好地理解如何消除语言的一些细微差别,而我逐渐意识到这些细微差别比我想象的要多.我并不是说这是一件坏事——事实上 (IMO) 可以期望 任何 语言灵活而复杂——但它确实让一个人错过了黑白世界不时组装...

为了结束这一点,有几点意见:
1) 所选答案包含一个链接,指向一个充满 Scala 脑筋急转弯的网站(我发现这对于尝试理解该语言中的一些上述夸克非常有帮助.)强烈推荐.
2)我确实遇到了另一个有趣的转折 - 而单括号(上面的例子)不起作用,将其更改为以下并且它工作得很好......

Epilogue: At the time of this edit there are posts detailing two possible explanations, both of which appear to contain elements of truth to them. Which one is actually Correct? I couldn't say with any degree of certainty...I'm just a guy who's still learning the language. That being said, I have changed the answer selection based upon the feeling that the one answer is (at least to some extent) encompassed within the other - so I've opted for the larger picture, as I think it will provide a broader meaning for someone else in search of an answer. Ironically, I was trying to get a better understanding of how to flatten out some of the little nuances of the language, and what I've come to realize is there are more of those than I had suspected. I'm not saying that's a bad thing - in fact (IMO) it's to be expected from any language that is as flexible and complex - but it sure does make a guy miss the black/white world of Assembly from time-to-time...

To draw this to an end, a couple observations:
1) the selected answer contains a link to a website full of Scala brain-benders (Which I found extremely helpful in trying to understand some of the aforementioned quarks in the language.) Highly recommended.
2) I did come across another interesting twist - whereas the single-parenthesis (example above) does not work, change it the following and it works just fine...

vmap += ("foo" -> "bar")

这可能与匹配方法/函数签名有关,但这只是我的猜测.

Which probably has something to do with matching method/function signatures, but that is just a guess on my part.

推荐答案

接受的答案实际上是错误的.

The accepted answer is actually wrong.

您没有得到 Map.+= 元组的原因是该方法被第二个方法重载,该方法需要两个或多个参数.

The reason you don't get tupling for Map.+= is that the method is overloaded with a second method that takes two or more args.

编译器只会在 args 数量错误时尝试元组.但是如果你给它两个参数,并且有一个方法需要两个参数,那么它就会选择它,即使它没有键入检查.

The compiler will only try tupling if the number of args is wrong. But if you give it two args, and there's a method that takes two, that's what it chooses, even if it fails to type check.

它不会开始尝试所有可能的组合,直到某些事情奏效,因为那会充满晦涩.(参见隐式.)

It doesn't start trying all possible combinations until something works because that would be fraught with obscurity. (Cf implicits.)

scala> def f(p: Pair[String, Int]) = { val (s,i) = p; s.toInt + i }
f: (p: Pair[String,Int])Int

scala> f("2",3)  // ok to tuple
res0: Int = 5

scala> trait F { def +=(p: Pair[String, Int]) = f(p) }
defined trait F

scala> val foo = new F {}
foo: F = $anon$1@6bc77f62

scala> foo += ("2",3)  // ok to tuple
res1: Int = 5

scala> trait G { def +=(p: Pair[String, Int]) = f(p); def +=(p:(String,Int),q:(String,Int),r:(String,Int)*) = f(p)+f(q)+(r map f).sum }
defined trait G

scala> val goo = new G {}
goo: G = $anon$1@183aeac3

scala> goo += ("2",3)    // sorry
<console>:12: error: type mismatch;
 found   : String("2")
 required: (String, Int)
              goo += ("2",3)
                      ^

scala> goo += (("2",3),("4",5),("6",7))
res3: Int = 27

我不会提到你和我的朋友,-Xlint,它会警告不合适的 arg 改编:

I'd be remiss not to mention your friend and mine, -Xlint, which will warn about untoward arg adaptations:

apm@mara:~/tmp$ skala -Xlint
Welcome to Scala version 2.11.0-20130811-132927-95a4d6e987 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def f(p: Pair[String, Int]) = { val (s,i) = p; s.toInt + i }
f: (p: Pair[String,Int])Int

scala> f("2",3)
<console>:9: warning: Adapting argument list by creating a 2-tuple: this may not be what you want.
        signature: f(p: Pair[String,Int]): Int
  given arguments: "2", 3
 after adaptation: f(("2", 3): (String, Int))
              f("2",3)
               ^
res0: Int = 5

scala> List(1).toSet()
<console>:8: warning: Adapting argument list by inserting (): this is unlikely to be what you want.
        signature: GenSetLike.apply(elem: A): Boolean
  given arguments: <none>
 after adaptation: GenSetLike((): Unit)
              List(1).toSet()
                           ^
res3: Boolean = false

关于适应的危险,请参阅自适应推理谜题这个新的很常见 因为我们了解到括号的存在或不存在在很大程度上是一种风格问题,当括号真的很重要时,使用错误会导致类型错误.

On the perils of adaptation, see the Adaptive Reasoning puzzler and this new one that is pretty common because we learn that the presence or absence of parens is largely a matter of style, and when parens really matter, using them wrong results in a type error.

在存在重载的情况下调整元组:

Adapting a tuple in the presence of overloading:

scala> class Foo {
     | def f[A](a: A) = 1    // A can be (Int,Int,Int)
     | def f[A](a: A, a2: A) = 2
     | }
defined class Foo

scala> val foo = new Foo
foo: Foo = Foo@2645d22d

scala> foo.f(0,0,0)
<console>:10: warning: Adapting argument list by creating a 3-tuple: this may not be what you want.
        signature: Foo.f[A](a: A): Int
  given arguments: 0, 0, 0
 after adaptation: Foo.f((0, 0, 0): (Int, Int, Int))
              foo.f(0,0,0)
                   ^
res9: Int = 1

这篇关于Scala 括号语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆