Function not returning value when called - scala

So, I'm a bit new to Scala, and I don't really understand how it reads code, compared to other languages.
Take this simple example:
#main
def roll():Int =
var x:Int = (math.random*6+1).toInt
return x
def print =
for i <- 1 to 10 do
println(roll())
The above code returns nothing, however, should I flip the methods (put print "method" before "roll"), it will now work. I find this incredibly strange. Where have I done wrong? I just simply want to call a method/function that randomizes a number, and print it using a new function to call it. Anyone who can help me?

#main annotation is applied to method (one, the following after it), i.e. for :
#main
def roll():Int =
var x:Int = (math.random*6+1).toInt
return x
def print =
for i <- 1 to 10 do
println(roll())
Your main method will be roll and only it will be invoked during program execution. And print is just a declared method which is not called.
And when you "flip them":
#main
def print =
for i <- 1 to 10 do
println(roll())
def roll():Int =
var x:Int = (math.random*6+1).toInt
return x
print becomes the main method, so it is invoked and it calls the declared roll method in the loop.
Also read annotations doc.

Related

Changing a parameter in a function in Scala

I'm trying to pass a parameter by reference and update in a function.
object CallByName {
private def inc(x: => Int): Unit = {
x += 1
}
def main(args: Array[String]): Unit = {
var x = 0
inc(x)
println(x)
}
}
But x+=1 is marked as an error:
Reassignment to val
I've come across this statement:
Mutating the input parameters is often seen as bad style and makes it
harder to reason about code.
Then how can I alternatively achieve what I want?
Mutating the input parameters is often seen as bad style and makes it harder to reason about code.
This is very true and, in my opinion, should be followed at all times.
pass a parameter by reference
x: => Int is not a parameter by reference, it is a by-name parameter.
Then how can I alternatively achieve what I want?
private def inc(x: Int): Int = {
x + 1
}
var x = 0
x = inc(x)
If you do insist on changing input parameter, you can use AtomicInteger for example and mutate it within your inc method.
I'm trying to pass a parameter by reference and update in a function.
Scala does not support pass-by-reference. The default is pass-by-value, and it is possible to explicitly define individual parameters as call-by-name, but those are the only two modes supported.
object CallByName {
private def inc(x: => Int): Unit = {
x += 1
}
}
That's not pass-by-reference, that is call-by-name. Check out the name of the object, it says so right there: CallByName.
Then how can I alternatively achieve what I want?
Unfortunately, you don't say what you want to achieve, so it's impossible to say. The only thing you do say is that you want pass-by-reference, and for that, the answer is simple:
You can't. Scala does not support pass-by-reference, period.

In a scala macro called with an implicit def, how can I get the source statement of the caller to the implicit def as a string?

I'm trying to write an implicit def macro that captures the invoking statement (and preferably nothing else) as a string, that can hopefully be used just by having the desired output object as an implicit parameter. But I'm having some trouble getting it to work with multi line statements.
For example:
case class HowWasICalled(statement:String, lineNumber:Int)
object HowWasICalled {
implicit def generate: HowWasICalled = macro macro_impl
}
def callMe(something: Any)(implicit context: HowWasICalled)
// macro: c is the blackbox Context
def macro_impl(c: blackbox.Context): c.Expr[HowWasICalled] = { ... }
And the first attempt at implementing a method inside the macro that returns the invoking statement as a string:
def makeString:String = show(c.macroApplication)
But, this only returned "HowWasICalled.generate". I actually wanted the statement invoking callMe.
I was hoping the following would work, but it doesn't. The -Yrangepos compiler flag does not seem to result in range positions in def macros? :(
def makeString:String = {
if (c.enclosingPosition.isRange) {
new String(c.enclosingPosition.source.content.slice(
c.enclosingPosition.start,
c.enclosingPosition.end
))
}
}
The closest I got to any working implementation doesn't exactly capture just statement nor the entire statement, but at least I get the line of source invoking callMe.
def makeString:String = {
val lineNumber = c.enclosingPosition.line
val lineIndex = lineNumber-1
c.enclosingPosition.source.lineToString(lineIndex)
}
How can I improve the macro to handle the following case? It should ideally generate something like a HowIWasCalled("callMe( 1 + 2 )", 123) given the following input
0; 0; 0; val x = callMe(1 +
2)

Overriding methods map and flatMap in class extending trait Iterator

As a Scala beginner I'm trying to implement a counter for every item of an Iterator being retrieved and processed in a for expression as well as a counter incremented every time a new iteration over one of the "loops" of the expression (outer loop and nested loops) is started. The requirement is to accomplish this without simply placing a statement like counter = counter + 1 at numerous locations in the for expression.
The following listing shows my proposed solution to this problem and I would like to know, why method next implementing Iterator's abstract member gets called (and the corresponding counter is incremented) whereas flatMap and map overriding their pendants defined in trait Iterator (and calling them via super) are not called at all.
object ZebraPuzzle {
var starts = 0
var items = 0
class InstrumentedIter[A](it: Iterator[A]) extends Iterator[A] {
private val iterator = it
def hasNext = it.hasNext
def next() = {
items = items + 1
it.next()
}
override def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Iterator[B] = {
starts = starts + 1
super.flatMap(f)
}
override def map[B](f: (A) ⇒ B): Iterator[B] = {
starts = starts + 1
super.map(f)
}
} // inner class InstrumentedIter
The corresponding for expression looks like this:
def solve = {
val first = 1
val middle = 3
val houses = List(first, 2, middle, 4, 5)
for {
List(r, g, i, y, b) <- new InstrumentedIter(houses.permutations)
if ...
List(eng, span, ukr, jap, nor) <- new InstrumentedIter(houses.permutations)
if ...
if ...
if ...
List(of, tea, milk, oj, wat) <- new InstrumentedIter(houses.permutations)
if ...
...
} yield ...
...
}
...
} // standalone singleton object ZebraPuzzle
I would be grateful if someone could give me a hint how to solve the given problem in a better way. But most of all I am interested to know why my solution overriding Iterator's map and flatMap doesn't work like expected by my somewhat limited brain ;-)
Regards
Martin
In the meanwhile I managed to find the answer myself. The problem with my solution is that withFilter returns a reference to a newly created AbstractIterator, not an InstrumentedIterator. As a possible solution this reference can be passed to the constructor of a wrapper class like InstrumentedIterator that mixes in trait Iterator and overrides methods map and flatMap. These methods can then do the counting ...
Regards
Martin
Your lines
List(...) <- Iterator
don't call map and flatmap. They call unapply in the List companion object which unpacks Iterators into tuples.
To call map or flatMap you need something like
item <- Iterator
You need to either define a companion object for InstrumentedIter with an unapply method or use the map/flatMap syntax in your for comprehension.

Run a script and get each lines result

I want to write a simple Scala script that runs some methods that are defined in another file.
Each line that runs this method requires information that won't be available until runtime. For simplicity sakes, I want to abstract that portion out.
Thus, I want to use Currying to get the result of each line in the script, then run the result again with the extra data.
object TestUtil {
// "control" is not known until runtime
def someTestMethod(x: Int, y: Int)(control: Boolean): Boolean = {
if (control) {
assert(x == y)
x == y
} else {
assert(x > y)
x > y
}
}
}
someTestMethod is defined in my primary codebase.
// testScript.sc
import <whateverpath>.TestUtil
TestUtil.someTestMethod(2,1)
TestUtil.someTestMethod(5,5)
Each line should return a function, that I need to rerun with a Boolean.
val control: Boolean = true
List[(Boolean) -> Boolean) testFuncs = runFile("testScript.sc")
testFuncs.foreach(_(control)) // Run all the functions that testScripts defined
(Sorry if this is a weird example, it's the simplest thing I can think of)
So far I have figured out how to parse the script, and get the Tree. However at that point I can't figure out how to execute each individual tree object and get the result. This is basically where I'm stuck!
val settings = new scala.tools.nsc.GenericRunnerSettings(println)
settings.usejavacp.value = true
settings.nc.value = true
val interpreter: IMain = new IMain(settings)
val treeResult: Option[List[Tree]] = interpreter.parse(
"""true
| 5+14""".stripMargin)
treeResult.get.foreach((tree: Tree) => println(tree))
the result of which is
true
5.$plus(14)
where 5 + 14 has not been evaluated, and I can't figure out how, or if this is even a worthwhile route to pursure
In the worst case you could toString your modified tree and then call interpreter.interpret:
val results = treeResult.get.map { tree: Tree => interpreter.interpret(tree.toString) }
It seems like it would be better to have the other file evaluate to something that can then be interpreted passing control (e.g. using the scalaz Reader Monad and for/yield syntax). But I assume you have good reasons for wanting to do this via an extra scala interpreter.

How to put methods in sets?

def m(x: Int): Any = { }
var set = new HashSet[Int => Any]
set += m
set += m
set.size is now 2, and set.contains(m) is false, because apparently m is partially applied two times and two function objects is created. If m is a function, it works as expected. I want to treat the functions as equals if they reference the same method. Can this be done? (without turning to maps with key return for removal, or passing around other intermediate variables)
Use val fun = m _ to transform the method into a function before adding it.
Doing set += m implicitly creates a new function which is not equal to the function created when doing set.contains(m), e.g. both uses of m in a function context create a completely new and thus different function object. (Sorry, I just saw, you’ve already said that.)
This is okay, if you just need the get the methods into the set somehow and then use the set for all referencing. So the following works as well:
def m(x: Int): Any = { }
var set = new HashSet[Int => Any]
set += m
val fun = set.head // should not use head in real code but an iterator
set.contains(fun)
Addition:
or passing around other intermediate variables
There is no such thing as a method object in Scala. So I don’t think it is possible to compare two methods unless you compare their name. (Might be possible using reflection, but I’m not sure about that and it would be pretty nasty to do as well – you wouldn’t have a set of functions then but of method references which you’d need to transform to proper methods and back again.)
You can wrap the method into a lambda with the same signature:
val m1 = (i:Int) => m(i)
set += m1
set += m1
println( set.size ) // Outputs "1"
println( set contains m1 ) //Outputs "true"