Groovy multi-methods - methods

I started learning Groovy and got curious about its method invocation resolving. I've read and understand what is groovy multi-methods, but I can't understand behaviour of next code snippet
def method(int i) {
println 1
}
def method(Number n) {
println 2
}
Number n = 1
method n # returns 1 as expected
method((Number) n) # returns 2 which I can't understand why
Is there some exclusion about casting? Can someone please explain this behaviour?

I think what you see here is a result of value in-/out-boxing.
If you pass a value of actial type Integer in, the value is converted to int during method lookup and the 1st method is called.
If you cast the value to Number or it's sub-class explicitly the inboxing does not happen and the method expecting Number is invoked.
I extended your code a bit:
def method(int i) {
println "int > $i / ${i.getClass()}"
}
def method(Number i) {
println "Number > $i / ${i.getClass()}"
}
def method(float i) {
println "float > $i / ${i.getClass()}"
}
Number n = 1
Number nFloat = 1.0f
Number nDouble = 1.0d
method n
method( new BigInteger( n ) )
method( (Number)n )
method( new BigInteger( n ) as int )
method nFloat
method nDouble
prints
int > 1 / class java.lang.Integer
Number > 1 / class java.math.BigInteger
Number > 1 / class java.lang.Integer
int > 1 / class java.lang.Integer
float > 1.0 / class java.lang.Float
Number > 1.0 / class java.lang.Double
Hope it is getting clearer now...

Related

How to make a traditional for-loop in Kotlin

JavaScript
for (var x = 0; x < 360; x += 0.5)
{
// ...
}
How do I do this in Kotlin?
Note that my step size is a floating point and so a regular range won't work:
for (x in 0.0 until 360.0 step 0.5) {
// ...
}
I also need to exclude the ending value, hence why I'm using until.
I will resort to a while loop for now:
var x = 0.0;
while (x < 360.0) {
// ...
x += 0.5
}
There isn't a way to do this right now in Kotlin because Kotlin does not have "traditional" for loops. I believe you're right in choosing a while loop. In fact, traditional for loops are just while loops in disguise:
for (init; condition; post;) {
// do something
}
can always be rewritten,
init
while (condition) {
// do something
post
}
with no change in behavior, because the init statement will always execute and the condition will always be checked before the loop runs even once. One thing this construct can't give you is a variable that's only scoped to this block. If you're really after that behavior, the following would work, though it's not very idiomatic.
for (x in generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0}) {
println(x)
}
If you're using a Sequence, you might also be interested in the more idiomatic forEach:
generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0 }.forEach { x ->
// do something
}
As repeated addition is just a shorthand for multiplication you can look at for (x in 0.0 until 360.0 step 0.5) as "do something for as many times as 0.5 fits in 360". Therefore it would make sense to express it like this:
val times = (360 / 0.5).toInt()
repeat(times){
}
of cause you can also inline times to
repeat(times = (360 / 0.5).toInt()){
}
The advantage is that you skip the sequence generation. Con -- you lose the access to your counting variable x.
see also https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html
I agree with Answer by #AdamYakes.
Since the until operator is not available for Floating value type, you can not use
it for floating step value.
However, If you still want to use
for (x in 0.0 until 360.0 step 0.5) {
// use value
}
you can do that as following:
for (x in 0 until 3600 step 5) {
// use (value / 10)
}
Kotlin is so flexible that one could hack a custom solution:
private infix fun (((Double) -> Unit, Double) -> Unit).step(step: Double) =
fun(action: (Double) -> Unit) = this(action, step)
private infix fun Double.upto(to: Double) =
fun(action: (Double) -> Unit, step: Double) {
var v = this
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
(0.0 upto 360.0 step 0.5) {
println(it)
}
}
What I did above is to create two infix functions.
The upto() infix function can be used with two Doubles: it takes 0.0 upto 360.0 and returns a function that expects two arguments: an action function and the step double value.
The step infix function can be used with functions returned by upto() combined with a Double (so f step 0.5). It returns a function that calls the upto() function passing the step value and the user's { ... } block that gets called for each iteration.
Short and convoluted.
A simpler alternative:
inline fun doubleFor(
from: Double, to: Double, step: Double, action: (Double) -> Unit
) {
var v = from
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
doubleFor(0.0, 360.0, 0.5) {
println(it)
}
}
A good IDE would show the argument names next to the values making the meaning of the arguments in the usage code obvious.
A third approach can be found at https://stackoverflow.com/a/44332139/2933899 which allows one to write for(x in 0.0 .. 360.0 step 0.5) { println(x) } with the inconvenience that the top boundary value is included.
Run these at https://pl.kotl.in/ZuR354Fas

How to do multiplication by using successor and predecessor in Scala

I am a beginner of programming language. Right now, I am working on a Scala project, which requires us to calculate the sum of the product and the exponentiation of two non-negative integers without using any Math functions and signs but only allows to use successor and predecessor. The functions do count for us. So I need to define addition in terms of those two integers, then define multiplication in terms of addition and exponents in terms of multiplication. So far, I've only come up with the solution for getting sum. Could you please help me to obtain the other parts? I think (if firstNum = 1, secondNum = 3) the product of these two can be obtained by using sum_1(sum_1(sum_1(a,0),a),a) But I really don't know how to write it in Scala code. Many thanks!
import io.StdIn._
val num = readLine("\n\nFor counting the sum, multiplication and exponentiation of two integers.\nPlease enter those two integers in (x,y) format: ")
val comma = num.indexOf(",")
val last = num.indexOf(")")
val firstNum = num.substring(1,comma).toInt
val secondNum = num.substring(comma+1,last).toInt
def sum_1(a:Int,b:Int): Int = {
def succ(a:Int): Int = a + 1
def pred(b:Int): Int = b - 1
if (b < 1) a
else {
succ(a)
pred(b)
sum_1(succ(a), pred(b))
}
}
//multiplication
//exponentation
println("1.The sum is " + sum_1(firstNum, secondNum) + ".")
println("2.The multiplication is .")
println("3.The exponentation is .")
You will have the following set of functions:
def succ(a:Int) = a+1
def pred(a:Int) = a-1
def sum(a:Int,b:Int):Int =
if(b<1) a
else sum(succ(a),pred(b))
def mul(a:Int,b:Int):Int =
if(b==0) 0
else if(b==1) a
else sum(mul(a,pred(b)),a)
def exp(a:Int, b:Int):Int =
if(b<1) 1
else mul(exp(a,pred(b)),a)
object mult extends App {
def succ(a: Int): Int = a + 1
def pred(b: Int): Int = b - 1
def sum(a: Int, b: Int): Int =
if (a == 0) b else sum(pred(a), succ(b))
def mult(a: Int, b: Int): Int =
if (a == 0) 0 else if (a == 1) b else sum(mult(pred(a), b), b)
def exp(a: Int, b: Int): Int =
if (b == 0) 1 else if (b == 1) a else mult(exp(a, pred(b)), a)
def printmult(a: Int, b: Int): Unit = println(s"$a * $b = ${mult(a, b)}")
(0 to 3).foreach { a => (0 to 3).foreach { b => printmult(a, b) } }
def printexp(a: Int, b: Int): Unit = println(s"$a ^ $b = ${exp(a, b)}")
(0 to 3).foreach { a => (0 to 3).foreach { b => printexp(a, b) } }
}

Numbers generation bad value

I would like to implementing Bernoulli numbers generation in Scala. I select this algorithm. I wrote following code:
def bernoulli(n: Int) = {
val a: Array[Fraction] = Array.fill(n + 1) {
new Fraction()
}
for (m <- 0 to n) {
a(m) = new Fraction(1, m + 1, 1 / (m + 1F))
for (j <- m to 1 by -1) {
val vc = a(j - 1)
vc.value= j * (vc.value - a(j).value)
}
}
a.head
}
class Fraction(var numerator: Int = 0, var denominator: Int = 0, var value: Float = 0)
But when I print bernoulli(5) it is not 0.
The code that you are using seems to work fine. The reason that you don't get 0 is because of floating point errors. If you want more accurate results, you can use BigDecimal rather than floats.
To use BigDecimal, use a(m) = new Fraction(1, m + 1, 1 / BigDecimal(m + 1)) and use BigDecimal for the class.
By using BigDecimal, you will get
bernoulli(5).value //> res0: BigDecimal = -1.00E-32
which is close to 0.

System Stack Error

So I have the following code for a Merge Sort in Ruby.
class MergeSort
def sort(array)
if array.length == 1 || array.length == 0
return array
end
firstHalf = array[0..array.length / 2]
secondHalf = array[(array.length / 2) + 1..array.length]
firstHalf = sort(firstHalf)
secondHalf = sort(secondHalf)
b = 0
c = 0
for i in (0..(firstHalf.length - 1))
while b < secondHalf.length && firstHalf[i] >= secondHalf[b]
array[c] = secondHalf[b]
b = b + 1
c = c + 1
array[c] = firstHalf[i]
c = c + 1
end
return array
end
end
array = [1,4,9,14,20,25]
puts MergeSort::new.sort(array)
When I run the code, I get a SystemStackError. Can someone tell me why this is happening? Thanks.
At a guess, once the array length gets to 3 (i.e. elements [0..2]), the call
firstHalf = array[0..array.length / 2]
evaluates to
0..1.5 and if 1.5 is rounded up to 2
which then calls sort [0..2] again
and eventually you get a stack overflow?
In order to call .new you have to have an initialize method in your class.
What you probably wanted to do was calling .sort on the class itself, in which case you have to prefix it with self, so:
class MergeSort
def self.sort(array)
...
Afterwards you can call it like this:
MergeSort.sort(array)

Why is filter in front of foldLeft slow in Scala?

I wrote an answer to the first Project Euler question:
Add all the natural numbers below one thousand that are multiples of 3 or 5.
The first thing that came to me was:
(1 until 1000).filter(i => (i % 3 == 0 || i % 5 == 0)).foldLeft(0)(_ + _)
but it's slow (it takes 125 ms), so I rewrote it, simply thinking of 'another way' versus 'the faster way'
(1 until 1000).foldLeft(0){
(total, x) =>
x match {
case i if (i % 3 == 0 || i % 5 ==0) => i + total // Add
case _ => total //skip
}
}
This is much faster (only 2 ms). Why? I'm guess the second version uses only the Range generator and doesn't manifest a fully realized collection in any way, doing it all in one pass, both faster and with less memory. Am I right?
Here the code on IdeOne: http://ideone.com/GbKlP
The problem, as others have said, is that filter creates a new collection. The alternative withFilter doesn't, but that doesn't have a foldLeft. Also, using .view, .iterator or .toStream would all avoid creating the new collection in various ways, but they are all slower here than the first method you used, which I thought somewhat strange at first.
But, then... See, 1 until 1000 is a Range, whose size is actually very small, because it doesn't store each element. Also, Range's foreach is extremely optimized, and is even specialized, which is not the case of any of the other collections. Since foldLeft is implemented as a foreach, as long as you stay with a Range you get to enjoy its optimized methods.
(_: Range).foreach:
#inline final override def foreach[#specialized(Unit) U](f: Int => U) {
if (length > 0) {
val last = this.last
var i = start
while (i != last) {
f(i)
i += step
}
f(i)
}
}
(_: Range).view.foreach
def foreach[U](f: A => U): Unit =
iterator.foreach(f)
(_: Range).view.iterator
override def iterator: Iterator[A] = new Elements(0, length)
protected class Elements(start: Int, end: Int) extends BufferedIterator[A] with Serializable {
private var i = start
def hasNext: Boolean = i < end
def next: A =
if (i < end) {
val x = self(i)
i += 1
x
} else Iterator.empty.next
def head =
if (i < end) self(i) else Iterator.empty.next
/** $super
* '''Note:''' `drop` is overridden to enable fast searching in the middle of indexed sequences.
*/
override def drop(n: Int): Iterator[A] =
if (n > 0) new Elements(i + n, end) else this
/** $super
* '''Note:''' `take` is overridden to be symmetric to `drop`.
*/
override def take(n: Int): Iterator[A] =
if (n <= 0) Iterator.empty.buffered
else if (i + n < end) new Elements(i, i + n)
else this
}
(_: Range).view.iterator.foreach
def foreach[U](f: A => U) { while (hasNext) f(next()) }
And that, of course, doesn't even count the filter between view and foldLeft:
override def filter(p: A => Boolean): This = newFiltered(p).asInstanceOf[This]
protected def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
trait Filtered extends Transformed[A] {
protected[this] val pred: A => Boolean
override def foreach[U](f: A => U) {
for (x <- self)
if (pred(x)) f(x)
}
override def stringPrefix = self.stringPrefix+"F"
}
Try making the collection lazy first, so
(1 until 1000).view.filter...
instead of
(1 until 1000).filter...
That should avoid the cost of building an intermediate collection. You might also get better performance from using sum instead of foldLeft(0)(_ + _), it's always possible that some collection type might have a more efficient way to sum numbers. If not, it's still cleaner and more declarative...
Looking through the code, it looks like filter does build a new Seq on which the foldLeft is called. The second skips that bit. It's not so much the memory, although that can't but help, but that the filtered collection is never built at all. All that work is never done.
Range uses TranversableLike.filter, which looks like this:
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
I think it's the += on line 4 that's the difference. Filtering in foldLeft eliminates it.
filter creates a whole new sequence on which then foldLeft is called. Try:
(1 until 1000).view.filter(i => (i % 3 == 0 || i % 5 == 0)).reduceLeft(_+_)
This will prevent said effect, merely wrapping the original thing. Exchanging foldLeft with reduceLeft is only cosmetic (in this case).
Now the challenge is, can you think of a yet more efficient way? Not that your solution is too slow in this case, but how well does it scale? What if instead of 1000, it was 1000000000? There is a solution that could compute the latter case just as quickly as the former.

Resources