Scala: Calling function dynamically - scala

I am very new to scala.
I am using rscala to integrate with R functions.
For example, I am using the following method to call an R function and retreive a String value.
Method Signature:
def invokeS0(function: Reference, args: Any*): String
Method Implementation
val v= rc.invokeS0("doPred","lemmas"->"Communicate,Design,Java,","frequency"->"3,3,1")
My Problem
However, rc.invokeS0 can call ANY function and thus have ANY number of arguments.
I'm thinking of building a wrapper method that takes the function name as a String and arguments as a Map. Perhaps something like this:
private def invokeRStringFunction(functionName: String = "testFunction", args: Map[String,String]): Unit =
{
/**Iterate through map to generate following code*/
val v= rc.invokeS0(functionName,mapKey1->mapValue1,mapKey2->mapValue2 etc etc)
}
But I am not sure how to write the code given that the number of arguments is dynamic. Frankly, I am not sure if it is possible, but thought I would check, just in case.
Any hints would be greatly appreciated.

Convert the Map[String, String] into a Seq[(String, String)] with args.toSeq, and then use the _* ascription to pass it as a sequence of arguments instead of just one.
def invokeRStringFunction(functionName: String, args: Map[String, String]): Unit
= rc.invokeS0(functionName, args.toSeq: _*)

Related

Scala passing varargs to another function that takes varargs

Why varargs can't be passed as another varargs without :_* ?
object Main {
def main(s: Array[String]): Unit = {
def someFunction(varars: String*) = {
someOtherFunction(varars) // Compilation ERRRO
someOtherFunction(varars:_*) // Works, but why ?
}
def someOtherFunction(someOtherVarars: String*): Unit = {
}
}
}
It's because varars is a single argument - an array of strings (note, that I'm not writing Array[String], because it is not the java Array, more details here), whereas by looking at the signature def someOtherFunction(someOtherVarars: String*): Unit, we can tell, that someOtherFunction takes multiple arguments of type String each. You cannot simply pass an array as the parameter to someOtherFunction, you need to "unfold" it first.
In other words an argument can be passed to someOtherFunction it has to be marked as a sequence argument. It would not make much sense to be able to pass varargs and varargs(1) to the single function. It's described in SLS ยง4.6.2.
"varargs"parameter means it can take any number of strings as an argument(i.e., a varargs field).
def someFunction(varars: String*): Seq[String] = {
varars }
if you define the above method and check for type of "varars" it has now become Seq[String] when you are using it. But when you pass it to another method which is expecting variableArgs type. It mismatch as it has become Seq[String] which should be converted to variable arguments using (someOtherVarars: _*).
_* operator tells the compiler to pass each element of the sequence as a separate argument, instead of passing it as a single argument.

How do I get ClassTag from String to pass to a Scala Function as a type parameter?

I have a Scala function that is defined like
def func[V: ClassTag, VD <: kafka.serializer.Decoder[V]](implicit tag: ClassTag[VD]) = {}
I have the class name of VD that I am going to use while calling this function as a string e.g. com.company.CustomDecoder. How do I call the function above with the correct ClassTag?
Elaboration :
I can call the function as
func[String, kafka.serializer.StringDecoder]
But how do I call this function given
val vClassStr = "java.lang.String"
val vDClassStr = "kafka.serializer.StringDecoder"
I prefer to type the evidence parameter out, so I would write the above as:
def func[V, VD <: kafka.serializer.Decoder[V]](data: Int)(implicit tag: ClassTag[VD])
Then you can just use tag in your code. Otherwise you can do it using a type bound and using the helper classTag[T] to get it:
val tag = classTag[VD]
I think you have some syntax issues in your example.
EDIT: If you need to just construct the types from strings, just use Class.forName from Java.
func(v: String, vd: String, data: Int) = {
val clz1 = Class.forName(v)
val clz2 = Class.forName(vd)
// etc
}

How to combine Maps with different value types in Scala

I have the following code which is working:
case class Step() {
def bindings(): Map[String, Any] = ???
}
class Builder {
private val globalBindings = scala.collection.mutable.HashMap.empty[String, Any]
private val steps = scala.collection.mutable.ArrayBuffer.empty[Step]
private def context: Map[String, Any] =
globalBindings.foldLeft(Map[String, Any]())((l, r) => l + r) ++ Map[String, Any]("steps" -> steps.foldLeft(Vector[Map[String, Any]]())((l, r) => l.+:(r.bindings)))
}
But I think it could be simplified so as to not need the first foldLeft in the 'context' method.
The desired result is to produce a map where the entry values are either a String, an object upon which toString will be invoked later, or a function which returns a String.
Is this the best I can do with Scala's type system or can I make the code clearer?
TIA
First of all, the toMap method on mutable.HashMap returns an immutable.Map. You can also use map instead of the inner foldLeft together with toVector if you really need a vector, which might be unnecessary. Finally, you can just use + to add the desired key-value pair of "steps" to the map.
So your whole method body could be:
globalBindings.toMap + ("steps" -> steps.map(_.bindings).toVector)
I'd also note that you should be apprehensive of using types like Map[String, Any] in Scala. So much of the power of Scala comes from its type system and it can be used to great effect in many such situations, and so these types are often considered unidiomatic. Of course, there are situations where this approach makes the most sense, and without more context it would be hard to determine if that were true here.

nested "if"/"match" statement in scala: better approach?

I have a series of validation functions that returns an Option[Problem], if any, or None if no validation problems are found.
I would like to write a simple function that calls each validation function, stop and return the first not-None result.
Naturally I can write this method in the "java-style", but I would like to know if a better approach exists.
EDIT
This was the original Java solution:
validate01(arg);
validate02(arg);
validate03(arg);
...
Each method throws an exception in case of problem. I would stay away from the exceptions while I'm writing Scala.
As an example, let's say we want to validate a String. Our validation function takes a String and a list of validators, which are functions from String to Option[Problem]. We can implement it in a functional manner like this:
def firstProblem(validators: List[String => Option[Problem]], s:String) =
validators.view.flatMap(_(s)).headOption
This creates a new list by applying each validation function to the string and keeping the result only if it is a Some. We then take the first element of this List. Because of the call to view, the list will be computed only as needed. So as soon as the first Problem is found, no further validators will be called.
If you have finite and known at compile time number of validations you may use .orElse on Options:
def foo(x: Int): Option[Problem] = ...
def bar(x: Int): Option[Problem] = ...
...
def baz(x: Int): Option[Problem] = ...
foo(1) orElse bar(2) orElse .. baz(n)
Maybe you want--assuming the validation functions take no arguments
def firstProblem(fs: (() => Option[Problem])*) = {
fs.iterator.map(f => f()).find(_.isDefined).flatten
}
You'll get an existing Option[Problem] if there are any, or None if they all succeed. If you need to pass arguments to the functions, then you need to explain what those arguments are. For example, you could
def firstProblem[A](a: A)(fs: (A => Option[Problem])*) = /* TODO */
if you can pass the same argument to all of them. You would use it like this:
firstProblem(myData)(
validatorA,
validatorB,
validatorC,
validatorD
)

How to define a method in Scala that returns a Java object?

I want to define a private method in scala singleton class that looks like;
private def createDomNode(tag: String, attrs: Map[String , String]): DomNode {
}
DomNode is Java type, not scala type. attrs is scala Map with both key and value being of type String.
But above gives error. What is the correct format?
Thanks Easy Angel for the answer. There is still some confusion. According to Programming in Scala book written by the inventor of the language, the below is a function:
def max(x: Int, y: Int): Int = {
if (x > y) x
else y
}
But your answer says it is method and not function. Can you kindly explain?
What is REPL?
You should just put =:
private def createDomNode(tag: String, attrs: Map[String , String]): DomNode = {
// ...
}
If you will not put = between method signature and body, then return type is Unit, so this:
def m(i: Int) {}
is the same as
def m(i: Int): Unit = {}
Response to the comment: What I described earlier is actually method, if you define it within object, class or trait definition. Function syntax would look like this:
val createDomNode: (String, Map[String , String]) => DomNode = { (tag, attrs) =>
// ...
}
As You can see I define val with name createDomNode of function type. It can also be written like:
val createDomNode: Function2[String, Map[String , String], DomNode] = { (tag, attrs) =>
// ...
}
here is another example. In this case I define method that generates new function each time you call it:
def createDomNode = (tag: String, attrs: Map[String , String]) => new DomNode
But it's important to understand, that method returns a "function that returns DomNode" in this case, but not DomNode itself.
About Programming in Scala reference. I think you are talking about Chapter 2 - Step 3 (in the intro)
As you can see max function is defined in REPL, and it's really function. Actually you can also write something like this:
class MyClass {
def myMethod(i: Int): Int = {
def myInnerFn(x: Int) = x * x
myInnerFn(i)
}
}
In this case myMethod is method and myInnerFn is function. So as you can see, it highly depends on the context. I believe this syntax for myInnerFn is just syntactic sugar for (I need to look in spec in order to say for sure):
val myInnerFn = (x: Int) => x * x
The same happens in REPL. And by the way that's because I wrote at the beginning:
if you define it within object, class or trait definition
Sorry, I need to be more clear about this and describe it in more detail in my second update.
I looked in Scala spec. Seems that I'm not totally correct when I say that myInnerFn is syntactic sugar for the function. but seems that it's called Method Type. You can find it in spec section 3.3.1 Method Type:
http://www.scala-lang.org/docu/files/ScalaReference.pdf
hope it will give you some clue, if you want to dive deeper in this. I think it's easy to get lost in terminology. You can function in 2 contexts. In first we have
Function - returns some value
Procedure - returns no value (or in Scala context it returns Unit)
And in second context:
Function - executable piece of code that can be passes around and treated as value
Method - belongs to the class
And it's sometimes not clear in what context it meant. For example I can tell you that myMethod is as function just because it has return value (or in other words: myMethod it's not procedure). I believe it's the same case in book.
One more thing. Sections 8.1, 8.2, 8.3 from Programming in Scala can help you to understand this terminology. And if I'm correct in my assumptions, what you think as Function is called First-class function in the book (it's described in section 8.3).
Hope this helps