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?
The postfix form requires no parentheses. The order of the operators in the postfix expressions determines the actual order of operations in evaluating the expression, making the use of parentheses unnecessary.
For a long time, Scala has supported a useful “trick” called infix operator notation. If a method takes a single argument, you can call it without the period after the instance and without parentheses around the argument.
infix operator (plural infix operators) (computing) an operator that is placed in between the operands like it is commonly used in arithmetical and logical formulae and statements. The plus sign in "2 + 2" is placed as an infix operator in arithmetic.
This is what I put together for myself after reading the spec:
a.m(b)
can be written a m b
.a.m
can be written a m
.For instance a.##(b)
can be written a ## b
and a.!
can be written a!
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)
. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With