How to declare in scala a default param in a method of an implicit class - scala

In order to use infix notation, I have the following example of scala code.
implicit class myclass(n:Int ){
private def mapCombineReduce(map : Int => Double, combine: (Double,Double) => Double, zero: Double )(a:Int, b:Double): Double =
if( a > b) zero else combine ( map(a), mapCombineReduce(map,combine,zero)(a+1,b) )
var default_value_of_z : Int = 0
def sum( z : Int = default_value_of_z) = mapReduce( x=>x , (x,y) => x+y+z, 0)(1,n)
def ! = mapCombineReduce( x=> x, (x,y) => x*y, 1)(1,n)
}
4 !
4 sum 1 //sum the elements from 1 to 7 and each time combine the result, add 1 to the result.
4 sum
Is there any way in scala 2.12 to run 4 sum without have a double declaration of the sum method inside myclass ?

No, because default arguments are only used if argument list is provided
def f(x: Int = 1) = x
f // interpreted as trying to do eta-expansion
In fact starting Scala 3 it will indeed eta-expand
scala> def f(x: Int = 1) = x
def f(x: Int): Int
scala> f
val res1: Int => Int = Lambda$7473/1229666909#61a1990e
so in your case you will have to write 4.sum() with argument list present.

Related

Why doesn't "1 Math.pow 2" work in scala?

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:
Implicit casting of the constant "1" to an instance of Int
Leveraging of the "Space notation" for methods that take a single parameter
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

How to take a constant Integer as input in Partial Function? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am new to scala, I have a use case where I want to define a partial function to add three numbers in which one number is constant and two
numbers can be passed as inputs and define another method which can take the partial
function as input and gives its cube as result.
Well... That depends on where is your constant coming from?
Choice 1 - Your function forms a closure with a constant present in scope.
val yourConstant = 10
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + yourConstant
}
pf((5, 10))
Choice 2 - Your function has a local constant.
val pf: PartialFunction[(Int, Int), Int] = {
case (x, y) => x + y + 10
}
pf((5, 10))
Also, as many others pointed out - this does not look like a use case of partial function. Are you sure that you want a Partial Function and not a partially applied function ?
if you were looking for a partially applied function then,
// first you need a curried function
// Curries function are function which can take parameters in steps to build intermidatary functions.
def normalDef(c: Int)(x: Int, y: Int): Int = c + y + x
// normalDef: normalDef[](val c: Int)(val x: Int,val y: Int) => Int
// now you can "partially apply" this "curried" function to your partially applied function
val addTo10PartiallyApplied = normalDef(10) _
// addTo10PartiallyApplied: (Int, Int) => Int = $Lambda$1240/1924827254#46202553
val total = addTo10PartiallyApplied(1, 2)
// total: Int = 13
The following partial function adds 12345 to each number in the tuple passed to it
scala> val addConstantTo: PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + 12345
| }
addConstantTo: PartialFunction[(Int, Int),Int] = <function1>
scala> addConstantTo((12, 34))
res4: Int = 12391
This expands on the concept, by programmatically defining a partial function which adds any number to the elements of a tuple:
scala> def addTo(c: Int): PartialFunction[(Int, Int), Int] = {
| case (a, b) => a + b + c
| }
addTo: (c: Int)PartialFunction[(Int, Int),Int]
scala> val pf = addTo(3)
pf: PartialFunction[(Int, Int),Int] = <function1>
scala> pf((1, 2))
res5: Int = 6
Let that sink in for a bit :)

Why is this function called multiple times?

In this function "f" :
def f(x: => Int) : Int = x * x * x //> f: (x: => Int)Int
var y = 0 //> y : Int = 0
f {
y += 1
println("invoked")
y
} //> invoked
//| invoked
//| invoked
//| res0: Int = 6
"f" is invoked same amount of times as "x" parameter is multiplied.
But why is function invoked multiple times ?
Should "f" not expand to 1 * 1 * 1 not 1 * 2 * 3 ?
Your x is not a function, it is a by-name parameter, and its type is a parameterless method type.
Parameterless method type means the same as def x, something that is evaluated every time you reference it. By reference, we mean x and not x.apply() or x().
The expression you're passing to your function f is evaluated every time x is referenced in f. That expression is the whole thing in braces, a block expression. A block is a sequence of statements followed by the result expression at the end.
Here's another explanation: https://stackoverflow.com/a/13337382/1296806
But let's not call it a function, even if it behaves like one under the covers.
Here is the language used in the spec:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#by-name-parameters
It's not a value type because you can't write val i: => Int.
It was a big deal when they changed the implementation so you could pass a by-name arg to another method without evaluating it first. There was never a question that you can pass function values around like that. For example:
scala> def k(y: => Int) = 8
k: (y: => Int)Int
scala> def f(x: => Int) = k(x) // this used to evaluate x
f: (x: => Int)Int
scala> f { println("hi") ; 42 }
res8: Int = 8
An exception was made to "preserve the by-name behavior" of the incoming x.
This mattered to people because of eta expansion:
scala> def k(y: => Int)(z: Int) = y + y + z
k: (y: => Int)(z: Int)Int
scala> def f(x: => Int) = k(x)(_) // normally, evaluate what you can now
f: (x: => Int)Int => Int
scala> val g = f { println("hi") ; 42 }
g: Int => Int = <function1>
scala> g(6)
hi
hi
res11: Int = 90
The question is how many greetings do you expect?
More quirks:
scala> def f(x: => Int) = (1 to 5) foreach (_ => x)
f: (x: => Int)Unit
scala> def g(x: () => Int) = (1 to 5) foreach (_ => x())
g: (x: () => Int)Unit
scala> var y = 0
y: Int = 0
scala> y = 0 ; f { y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
scala> y = 0 ; g { y += 1 ; println("hi") ; () => y }
hi
y: Int = 1
scala> y = 0 ; g { () => y += 1 ; println("hi") ; y }
hi
hi
hi
hi
hi
y: Int = 5
Functions don't cause this problem:
scala> object X { def f(i: Int) = i ; def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
res12: Int = 0
scala> trait Y { def f(i: Int) = i }
defined trait Y
scala> object X extends Y { def f(i: => Int) = i+1 }
defined object X
scala> X.f(0)
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object X of type (i: => Int)Int
and method f in trait Y of type (i: Int)Int
match argument types (Int)
X.f(0)
^
Compare method types:
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#method-types
This is not a pedantic distinction; irrespective of the current implementation, it can be confusing to think of a by-name parameter as "really" a function.
Another way of saying what has already been said is that inside f you invoke the function x three times. The first time it increments the y var and returns 1. The second time it again increments y returning 2 and the third time it again increments y and returns 3.
If you want it invoked only once then you may want to do something like this:
def f(x: => Int) : Int = x * x * x
var y = 0
lazy val xx = {
y += 1
println("invoked")
y
}
f {xx}
This will print 'invoked' only once and result in a returned value of 1.
x: T means need a T value.
x: => T means need a T value, but it is call by name.
x: () => T This means need a function given nothing to T
However, this question is not related to the difference between function and method.
The reason is call by name is invoked every time you try to use it.
change to call by value def f(x: Int) : Int, it will only invoke once.
Because you increment y by 1 every time the argument is used inside f
The result which your function f() returns is changing, because there is a global variable that is incremented with every subsequent call to that function.
the x in f(x: => Int) is interpreted as "some function that returns Int". So it has to be called 3 times to evaluate the x*x*x expression. With every call, you increment the global variable and return the result, which is how you arrive at three subsequent natural numbers (because the global variable is initialized to 0). Hence 1*2*3.

call a def within a block

If there is any way to call a def from a block
def factor (n: Int) : Int = if (n == 0 ) 1 else n * factor(n-1)
val i = 1000
i.toString.foreach ( x => sum += factor(x.toInt) )
at the end I want to get the sum of factorial of every digit
But it seems like def doesn't return a value, everytime is 0
How to fix it?
Thanks!
The problem actually has nothing to do with Scala per se; your code and your def are fine. The issue is with toInt:
scala> '3'.toInt
res7: Int = 51
toInt doesn't actually convert it as a decimal digit, but as a unicode (ish?) character value. These are producing very large numbers which go beyond what factor can handle:
scala> factor(6)
res8: Int = 720
scala> factor(20)
res9: Int = -2102132736
scala> factor(100)
res10: Int = 0
So instead use (thanks to Luigi)
x.asDigit

Scala methods ending in _=

I seem to remember Scala treating methods ending in _= specially, so something like this:
object X { var x: Int = 0; def y_=(n : Int) { x = n }}
X.y = 1
should call X.y_=(1). However, in 2.8.0 RC1, I get an error message:
<console>:6: error: value y is not a member of object X
X.y = 1
^
Interestingly, just trying to call the method without parentheses fails as well:
scala> X.y_= 1
<console>:1: error: ';' expected but integer literal found.
X.y_= 1
^
Am I misremembering something which does actually exist or did I just invent it out of whole cloth?
This is one of those corner cases in Scala. You cannot have a setter without a getter and vice versa.
The following works fine:
scala> object X {
| var x: Int = 0
| def y = x
| def y_=(n: Int) { x = n }
| }
defined module X
scala> X.y = 45
scala> X.y
res0: Int = 45
scala> object X { var x: Int = 0; def y_=(n : Int) { x = n }}
defined module X
scala>
scala> X y_= 1
scala> X.x
res1: Int = 1
scala> object X { var x: Int = _; def y = x ; def y_=(n: Int) { x = n } }
defined module X
scala> X.y = 1
scala> X.y
res2: Int = 1
scala>