Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
660 views
in Technique[技术] by (71.8m points)

dictionary - When to use parenthesis in Scala infix notation

When programming in Scala, I do more and more functional stuff. However, when using infix notation it is hard to tell when you need parenthesis and when you don't.

For example the following piece of code:

def caesar(k:Int)(c:Char) = c match {
    case c if c isLower => ('a'+((c-'a'+k)%26)).toChar
    case c if c isUpper => ('A'+((c-'A'+k)%26)).toChar
    case _ => c
}

def encrypt(file:String,k:Int) = (fromFile(file) mkString) map caesar(k)_

The (fromFile(file) mkString) needs parenthesis in order to compile. When removed I get the following error:

Caesar.scala:24: error: not found: value map
    def encrypt(file:String,k:Int) = fromFile(file) mkString map caesar(k)_
                                                                 ^
one error found

mkString obviously returns a string on which (by implicit conversion AFAIK)I can use the map function.

Why does this particular case needs parentheses? Is there a general guideline on when and why you need it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is what I put together for myself after reading the spec:

  • Any method which takes a single parameter can be used as an infix operator: a.m(b) can be written a m b.
  • Any method which does not require a parameter can be used as a postfix operator: a.m can be written a m.

For instance a.##(b) can be written a ## b and a.! can be written a!

  • Postfix operators have lower precedence than infix operators, so foo bar baz means foo.bar(baz) while foo bar baz bam means (foo.bar(baz)).bam and foo bar baz bam bim means (foo.bar(baz)).bam(bim).
  • Also given a parameterless method m of object a, a.m.m is valid but a m m is not as it would parse as exp1 op exp2.

Because there is a version of mkString that takes a single parameter it will be seen as an infix opertor in fromFile(file) mkString map caesar(k)_. There is also a version of mkString that takes no parameter which can be used a as postfix operator:

scala> List(1,2) mkString
res1: String = 12

scala> List(1,2) mkString "a"
res2: String = 1a2

Sometime by adding dot in the right location, you can get the precedence you need, e.g. fromFile(file).mkString map { }

And all that precedence thing happens before typing and other phases, so even though list mkString map function makes no sense as list.mkString(map).function, this is how it will be parsed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...