In scala the following works
1 max 2
But the following don't
1 Math.pow 2
or
import Math.pow
1 pow 2
Can you explain why?
In scala the following works
1 max 2
But the following don't
1 Math.pow 2
or
import Math.pow
1 pow 2
Can you explain why?
There are a couple of things going on here. In a nutshell:
In the case of 1 max 2, the constant 1 is implicitly cast as an Int (i.e. an instance of class Int).
Since the Int class defines a method called "max" which takes a single parameter, you can use the space or infix notation. The following are all equivalent (run in spark-shell):
scala> 1 max 2
res8: Int = 2
scala> 1.max(2)
res9: Int = 2
scala> val x = 1 // Note the result type here is Int
x: Int = 1
scala> x.max(2)
res10: Int = 2
scala> x max (2)
res11: Int = 2
scala> 1 // Note the result type here is *also* Int
res12: Int = 1
scala> 1. // Here are all of the methods that are defined for an Int
!= + << >> byteValue ensuring formatted isInfinity isValidByte isWhole notify signum toChar toInt toString until
## - <= >>> ceil eq getClass isInstanceOf isValidChar longValue notifyAll synchronized toDegrees toLong unary_+ wait
% -> == ^ compare equals hashCode isNaN isValidInt max round to toDouble toOctalString unary_- |
& / > abs compareTo floatValue intValue isNegInfinity isValidLong min self toBinaryString toFloat toRadians unary_~ →
* < >= asInstanceOf doubleValue floor isInfinite isPosInfinity isValidShort ne shortValue toByte toHexString toShort underlying
Note that there are a whole bunch of methods available on an Int for example max, min, +, - and so on. Looking at the signature of say, +, we can see that + is a method that takes a single parameter. Therefore we can do the following:
scala> 1 + 2 // No surprises here
res15: Int = 3
scala> 1.+(2) // Huh? This works because + is a method of Int that takes a single parameter.
// This is effectively the same as your max example.
res16: Int = 3
scala> 1.+ // Here are the signatures of the + method.
def +(x: Char): Int
def +(x: Long): Long
def +(x: Float): Float
def +(x: Short): Int
def +(x: Double): Double
def +(x: Byte): Int
def +(x: String): String
def +(x: Int): Int
scala> 1 + 'A' // From the above, we can see that the following is also valid
res17: Int = 66 // because the return type is Int
scala> 1 + "41"
res18: String = 141 // In this case, the + operator is a String concatenation operator Because the return type is String
scala> 1 + "x"
res19: String = 1x // Also because the return is String, but possible more intuitive.
To the pow part of the question.
Math.pow is a method that takes 2 parameters. Because it takes 2 parameters the space notation is not available to you. Also, pow is not a method that is associated with an Int. It is pretty much like a static method of the Math class (actually Math is an object). So, just like you can't say x.pow(y,z) you can not say 1.pow(y, z) on the other hand you can say Math.pow(x, 2) - to get x squared - because that matches the signature of the pow method.
Here is the signature of Math.pow:
scala> Math.pow
def pow(x$1: Double,x$2: Double): Double
This is a little less exciting than +, but it is clear that it takes 2 Doubles and returns a Double. The example of say Math.pow(2,2) works even though integers are supplied as parameters (when Doubles are required) because the Ints are automatically cast to Double.
I hope this helps explain what you are seeing. I encourage you to try these examples in spark-shell, sbt or some other scala REPL.
Methods doesn't the same signature:
override def max(that: Long): Long
def pow(x$1: Double,x$2: Double): Double
The first is a member of Int
* and can be called on 1
whereas the second is called on Math
object and must have two parameters.
* well actually of RichInt
by implicit conversion, but to an intuitive use perspective, it comes to the same thing so this subtlety shouldn't bother you
Method:
override def max(that: Int): Int = math.max(self, that)
is from scala.runtime.RichInt
class bc evry Int is wrapped by:
@inline implicit def intWrapper(x: Int) = new runtime.RichInt(x)
of class scala.LowPriorityImplicits
But RichInt
doesn't have any pow
method. And you have to respec Math.pow signature:
public static double pow(double a, double b)
and call it with 2 arguments or use your own developed wrapper, like:
object MainClass {
implicit class IntHelper(i:Int) {
def pow(p:Int): Double = Math.pow(i, p)
}
def main(args: Array[String]): Unit = {
println(1 pow 2)
}
}
output:
1.0
1 max 2
is just syntactic sugar for 1.max(2)
.
As 1
is an integer literal, all methods defined for scala.Int
can be applied in this way.
Unfortunately pow
is not a method of scala.Int
But you can find the related method in scala.math.BigDecimal
and scala.math.BigInt
.
So the following would work:
BigInt(1) pow 2
The max function you have used is from Int.
It's signature is:
def max(that: Int): Int
Since 1 is an Int, you can call 1 max 2
with infix notation. it is simply 1.max(2)
.
The pow function is from Math. It's signature is
def pow(x: Double, y: Double): Double
Since 1 is not a Math, you can't simply call 1 pow 2
. On the other hand in Int, there is no method such that def pow(that: Int): Int
.
The one you can use is pow(a,2)
which is the Math implementation.
Scala.Math Documentation says that pow
function takes two arguments of type Double and returns the value of the first argument raised to the power of the second argument.
This is the working version of the pow
function:
import Math.pow
val a: Double = 1
pow(a,2) // returns 1.0