Trying to wrap my head around the varying uses of the _. Right now I'm struggling with this example:
object Chapter9 extends App {
FileMatcher.filesEnding(".scala").foreach(println)
}
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) = {
for (file <- filesHere; if matcher(file.getName))
yield file
}
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
def filesContaining(query: String) =
filesMatching(_.contains(query))
def filesRegex(query: String) =
filesMatching(_.matches(query))
}
So clearly we want to abstract away the common work of looping/filtering/yielding for the varying types of matchers, makes sense to put it in a helper function.
I'm getting hung up on the _.endsWith part. My understanding is that this underscore (being the first and only one used in the method body) will be filled in by the first parameter, which in this case is query. I tried to test this theory by doing:
def filesEnding(query: String) = {
println(_: String)
}
But the program doesn't print anything. So what is _ here? How does Scala know what object to to search for an endsWith method on?
It looks like from output of the program that somehow file gets filled in for this underscore but have no idea how. Maybe the underscore remains a "wildcard" until it is used inside filesMatching's body and by that point the nearest enclosing scope is the for and the first "parameterisfile`?
Look at the signature for filesMatching(). Notice that it takes one argument of type String => Boolean. So its argument is a function that itself take a String argument and turns it into a Boolean.
Now remember that an anonymous function often looks something like this:
{ x => /* do something with x */ }
And in cases where x is used only once, then that can be abbreviated to a single _. So, working backwards, this
filesMatching(_.endsWith(query))
can be rewritten as this
filesMatching(x => x.endsWith(query))
So the filesMatching() code has its argument, a function that takes a string (which in the anonymous function I've called x). That function, matcher, is invoked with the string file.getName to get a Boolean. That boolean value is tested in an if clause:
if matcher(file.getName)
TL;DR: The underscore is shorthand for the file.getName string.
The canonical answer is What are all the uses of an underscore in Scala?
But -Xprint:parser shows
((x$1: String) => println((x$1: String)))
which is uninteresting except for the redundantly typed expression in the body of the function.
It doesn't seem to generate any extra code. The param is already a String.
I don't think your example compiles? Or I don't know what you're asking.
Explicit types can help debug when type of an anonymous function aren't inferred as you wish.
Edit: I gave this a try:
object Chapter9 extends App {
FileMatcher.filesEnding(".scala").foreach(println)
}
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) = {
for (file <- filesHere; if matcher(file.getName))
yield file
}
def filesEnding(query: String) = {
println(_: String)
}
}
An expression with an underscore as an anonymous function needs its expected type to tell it what type the underscore is, unless explicitly annotated as you did. But that is not common usage.
Instead of (_: Int) * 2, (i: Int) => i * 2, but that's a style question.
Related
I'm totally new with Scala, I have to maintain an old code, so I have to understand what it does.
Now I am stuck on this piece of code, it is about defining and calling a method.
This is the definition of the method:
private def myMethod[I, O](price: Long, id: Int)(i: I)(f: (I, String) => O): O = {
..some code..
}
this is the method call
myMethod(price, id)(b) {
..some code.. //single line of code, just calling an other function
}
I understood the part of having type parameter also of having multiple parameter (currying).
But what I didn't understand, is :
first of all this part: (f: (I, String) => O) , this is completely strange for me
second, why in the method call, it contains code after the { symbol, is it overriding the original method? even it's the case, it make no sense to override it when making the call
also, myMethod is supposed to return a value of type O , but in my code it's never affected to any variable. (EDIT: this point is clear now, I just misunderstood the code, nvm mind about it)
Please can any one clarify this points (especially the first and second one which are making me so confused)
EDIT
private var x : classX
myMethod(price, id)(b) {
x.listX //calling method without parameters
}
def listX (param1: ListFaFBI, param2: String): ListX ={
//returning an Object of type ListX, not a function
}
as you can see that myMethod is calling listX. if I understood well, myMethod is returning the method listX itself which has two parameters ListFaFBI (or I) and String and returning ListX (or O) as defined in (f: (I, String) => O)
f is a function that takes in an I and a String and returns an O. f: (I, String) => O is syntactic sugar for f: Function2[I, String, O].
The braces act essentially the same as parentheses would, although there are some differences, as they can be treated as blocks (See this question). The code inside the braces is actually a function literal, and it will be passed as f. Also see this question. Here,
myMethod(price, id)(b) { (i, s) =>
..some code..
}
would be syntactic sugar for
myMethod(price, id)(b)({ (i, s) =>
..some code..
})
I'm not sure what you mean by "in my code it's never affected to any variable", but I assume that what is returned is either irrelevant or that there is an implied return (in case the call to myMethod is at the end of a block.
first of all this part: (f: (I, String) => O) , this is completely strange for me
It is a function, taking a tuple of two elements of type I and String, and returns an O
why in the method call, it contains code after the { symbol, is it overriding the original method?
Your method is using multiple parameter list, and the syntax of the last parameter group is a block definition that allows to define the function value ((I, String) => O)
For example, if we had a method which takes a function in the same parameter list:
def foo(s: String, f: String => String)
Our implementation would look like this:
foo("hello", {
s => s + "world"
}
)
However, if we used a separate parameter group:
def foo(s: String)(f: String => String)
Our implementation look like this:
foo("hello") {
s => s + "world"
}
Which is more eye pleasing and reads nicer.
myMethod is supposed to return a value of type O , but in my code it's never affected to any variable
If you add the implemention of the method we can better help show you where it is returning a value of type O
I'm trying to implement something like clever parameters converter function with Scala.
Basically in my program I need to read parameters from a properties file, so obviously they are all strings and I would like then to convert each parameter in a specific type that I pass as parameter.
This is the implementation that I start coding:
def getParam[T](key : String , value : String, paramClass : T): Any = {
value match {
paramClass match {
case i if i == Int => value.trim.toInt
case b if b == Boolean => value.trim.toBoolean
case _ => value.trim
}
}
/* Exception handling is missing at the moment */
}
Usage:
val convertedInt = getParam("some.int.property.key", "10", Int)
val convertedBoolean = getParam("some.boolean.property.key", "true", Boolean)
val plainString = getParam("some.string.property.key", "value",String)
Points to note:
For my program now I need just 3 main type of type: String ,Int and Boolean,
if is possible I would like to extends to more object type
This is not clever, cause I need to explicit the matching against every possibile type to convert, I would like an more reflectional like approach
This code doesn't work, it give me compile error: "object java.lang.String is not a value" when I try to convert( actually no conversion happen because property values came as String).
Can anyone help me? I'm quite newbie in Scala and maybe I missing something
The Scala approach for a problem that you are trying to solve is context bounds. Given a type T you can require an object like ParamMeta[T], which will do all conversions for you. So you can rewrite your code to something like this:
trait ParamMeta[T] {
def apply(v: String): T
}
def getParam[T](key: String, value: String)(implicit meta: ParamMeta[T]): T =
meta(value.trim)
implicit case object IntMeta extends ParamMeta[Int] {
def apply(v: String): Int = v.toInt
}
// and so on
getParam[Int](/* ... */, "127") // = 127
There is even no need to throw exceptions! If you supply an unsupported type as getParam type argument, code will even not compile. You can rewrite signature of getParam using a syntax sugar for context bounds, T: Bound, which will require implicit value Bound[T], and you will need to use implicitly[Bound[T]] to access that values (because there will be no parameter name for it).
Also this code does not use reflection at all, because compiler searches for an implicit value ParamMeta[Int], founds it in object IntMeta and rewrites function call like getParam[Int](..., "127")(IntMeta), so it will get all required values at compile time.
If you feel that writing those case objects is too boilerplate, and you are sure that you will not need another method in these objects in future (for example, to convert T back to String), you can simplify declarations like this:
case class ParamMeta[T](f: String => T) {
def apply(s: String): T = f(s)
}
implicit val stringMeta = ParamMeta(identity)
implicit val intMeta = ParamMeta(_.toInt)
To avoid importing them every time you use getParam you can declare these implicits in a companion object of ParamMeta trait/case class, and Scala will pick them automatically.
As for original match approach, you can pass a implicit ClassTag[T] to your function, so you will be able to match classes. You do not need to create any values for ClassTag, as the compiler will pass it automatically. Here is a simple example how to do class matching:
import scala.reflect.ClassTag
import scala.reflect._
def test[T: ClassTag] = classTag[T].runtimeClass match {
case x if x == classOf[Int] => "I'm an int!"
case x if x == classOf[String] => "I'm a string!"
}
println(test[Int])
println(test[String])
However, this approach is less flexible than ParamMeta one, and ParamMeta should be preferred.
Given this definition:
class Foo(var x: String) {}
object Helper {
def model[T](get: ⇒ T, set: T ⇒ Unit) : Model[T] = new Model[T] {
override def getObject(): T = get
override def setObject(obj: T) { set(obj) }
}
}
I try to call model like this:
val f = new Foo("initial")
val stringModel = model(f.x, f.x = _)
But that doesn't work, the compiler gives me this, complaining about the underscore:
missing parameter type for expanded function ((x$1) => f.x = x$1)
If I change the definition of model to use two parameter lists like this:
def model[T](get: ⇒ T)(set: T ⇒ Unit) // rest is unchanged
Then I can call it like this:
model(f.x)(f.x = _)
Which I find nice and concise. I don't really mind doing it like this, though it makes method overloading harder. I would like to understand, however, why the second variant works and the first one doesn't?
The second variant works because Scala refines its types parameter-block by parameter-block. If you don't specify the type of your input parameter for the function, it's possible that it would change the type T that it has inferred based on the first parameter. If you push it to a separate parameter block, Scala's already decided what T must be by the time it hits that block, so it fills in the only possible value for the function argument type.
I am learning Scala (coming from a background of mostly Java). I am trying to wrap my head around the following code:
object Main {
def main(args : Array[String]) {
for (file <- filesEnding(".txt"))
println(file.getName)
}
private val filesHere = (new java.io.File(".")).listFiles
def filesMatching(matcher: String => Boolean) =
for (file <- filesHere; if matcher(file.getName))
yield file
def filesEnding(query: String) = filesMatching(_.endsWith(query))
/* Other matcher functions */
}
In particular I am confused where Scala gets the value for _ in each of the matcher functions. I can see that filesEnding is called with an argument of .txt. That argument is assigned to query. filesEnding then calls filesMatching with an argument consistent with a String => Boolean function. Finally I can see that file.getName is what eventually replaces the _ placeholder.
What I don't get is how Scala knows to put file.getName in place of _. I am having trouble tracing this code in my head and the eclipse debugger isn't much help in this situation. Can somebody walk me through what is happening in this code?
The _ is just a shorthand for making an anonymous function:
_.endsWith(query)
is the same as the anonymous function
fileName => fileName.endsWith(query)
This function is then fed as the argument matcher to filesMatching. Inside that function you can see the call
matcher(file.getName)
This calls the anonymous function with file.getName as the _ argument (which I called fileName in the explicit example).
If you write _.someMethod(someArguments), this desugars to x => x.someMethod(someArguments), so filesMatching(_.endsWith(query)) desugars to filesMatching(x => x.endsWith(query)).
So filesMatching is called with matcher being the function x => x.endsWith(query), i.e. a function which takes one argument x and calls x.endsWith(query) on that argument.
def func(arg: String => Int): Unit = {
// body of function
}
I mean this fragment:
String => Int
Short answer
Its a function that receives a String and returns a Int
Long answer
In Scala, functions are first class citizens. That means you can store them in variables or (like in this case) pass them around as arguments.
This is how a function literal looks like
() => Unit
This is a function that receives no arguments and returns Unit (java's equivalent to void).
This would be a function that receives a String as a parameter and returns an Int:
(String) => Int
Also, scala let's you drop the parenthesis as a form of syntactic sugar, like in your example. The preceding arg: is just the name of the argument.
Inside func you would call the function received (arg) like this:
val result = arg("Some String") // this returns a Int
As mentioned in Advantages of Scala’s Type System, it is a Functional type.
The article Scala for Java Refugees Part 6: Getting Over Java describes this syntax in its section "Higher-Order Functions".
def itrate(array:Array[String], fun:(String)=>Unit) = {
for (i <- 0 to (array.length - 1)) { // anti-idiom array iteration
fun(array(i))
}
}
val a = Array("Daniel", "Chris", "Joseph", "Renee")
iterate(a, (s:String) => println(s))
See? The syntax is so natural you almost miss it.
Starting at the top, we look at the type of the fun parameter and we see the (type1, …)=>returnType syntax which indicates a functional type.
In this case, fun will be a functional which takes a single parameter of type String and returns Unit (effectively void, so anything at all).
Two lines down in the function, we see the syntax for actually invoking the functional. fun is treated just as if it were a method available within the scope, the call syntax is identical.
Veterans of the C/C++ dark-ages will recognize this syntax as being reminiscent of how function pointers were handled back-in-the-day.
The difference is, no memory leaks to worry about, and no over-verbosity introduced by too many star symbols.
In your case: def func(arg: String => Int): Unit, arg would be a function taking a String and returning an Int.
You might also see it written (perhaps by a decompiler) as
def func(arg: Function1[String, Int]): Unit = {
// body of function
}
They are precisely equivalent.