How can I overload a constructor in Scala with a function as a parameter - scala

I am making a file searching program. This is contained in a "ParallelSearch" class. The signature is:
class ParallelSearch(condition: (Path, Int, String) => Boolean)
This is great and works. The user supplies a condition, that goes from a file path, a line number, and a string containing line content, to a Boolean. However, I would like to overload the constructor to allow the user to not specify file path or line number, and just search based on line contents. Like so:
def this(condition: String => Boolean) =
{
this((???): (Path, Int, String) => Boolean)
}
What I'm not sure about is what to put where I have the ??? right now. I can answer any other questions that will make understanding easier. Any help is appreciated! Thanks!

Related

How to declare variable argument abstract function in Scala

I m trying to declare function in trait that takes variable number of argument and during implementation of the trait I would expand the number of arguments. How can this done in Scala
I am expecting to come up with code like below.
trait Column {
def rule
}
case object FirstColumn extends Column{
def rule(s: String) : String
}
case object SecondColumn extends Column{
def rule(s1: String, s2: String) : String
}
I have tried using Strings* , but it is not allowing me to expand my number of arguments during implementation. I understand there are various way to handle this problem but i am specifically looking to have above signature for my team to write functions.
This is primarily expanding on my comment on the question. This answer gets you about as close as Scala lets you get to what you want, but it also shows why it's probably not a good idea to do what you're doing.
You can express (something close to) the type you want, but I'm not sure what you intend to gain. First, if you want to take different arglist types, then Column needs to be generic.
trait Column[-A] {
def rule(arg: A): String
}
Then we can implement your case objects as subclasses of an appropriate parameterization of this.
case object FirstColumn extends Column[String] {
def rule(arg: String): String =
"stub implementation"
}
case object SecondColumn extends Column[(String, String)] {
def rule(arg: (String, String)): String =
"stub implementation"
}
Note that FirstColumn and SecondColumn do not inherit from the same Column[A] as they don't implement the same method. We can get them to have a common type, but... not in a very useful way.
One option is to find a common supertype of Column[String] and Column[(String, String)], which (since the argument is contravariant) is akin to finding a common subtype of String and (String, String). The closest common subtype is... Null. That's not helpful unless you're only ever planning to pass null to your rule.
Instead, we can use existentials.
val foo: Column[_] = FirstColumn
val bar: Column[_] = SecondColumn
Now we've lost all type information. You can access the foo.rule slot and you can print it, but you can't call it because we don't know what we need to pass it. You'll have to do a cast to get it back to a usable format.
The point that I'm making here is that, yes, it's doable, but once you've lost as much type information as you're giving up, there's not much point. The type system is correctly telling us that foo and bar have virtually nothing in common except the existence of a method named rule which takes... some kind of argument. From a type theory perspective, it's hard to get more uninteresting than that.

Retaining type information in List[Any]

I'm using certain external library that has a method which is overloaded several times with different arguments, something like:
insertInto(index: Int, int: Int)
insertInto(index: Int, lng: Long)
insertInto(index: Int, dbl: Double)
insertInto(index: Int, str: String)
And a certain case class I'm using whose data I want to pass onto said methods, say:
case class C(str: String, lng: Long, dbl: Double, int: Int /* more values */)
val c = C("asd", 1, 1.1, 1)
Right now I'm using the library method like:
insertInto(1, c.int)
insertInto(2, c.lng)
insertInto(3, c.dbl)
insertInto(4, c.str)
//more insertions...
But since I'm always using the index of the value in the case classes I figured that maybe I could could save up on some lines of code (around 10) with something like the following:
c.productIterator.zipWithIndex.toList.foreach {
case (idx, value) => insertInto(idx, value)
}
But this doesn't work because I'd be iterating a List[Any] and therefore the compiler complains that I'm not passing the correct argument type to insertInto since Any is not String, Int, Long, Double, etc..
What would be the correct way of handling this? Thanks in advance
case class A[T](t:T)(implicit tag: ClassManifest[T]){
val newTag = tag
override def toString= t+" "+tag.toString
}
case class C(xs:List[Any])
val c=C(List(A("a"),A[Long](1), A[Double](1.1), A[Int](1)))
c.xs.foreach(println)
Try this. I am using Scala 2.9.3. In newer versions, you can use TypeTag and ClassTag. Check here
So now you have the class type information. You can devise some mechanism to map class type value as string to .class instance and then use asinstanceof to cast it.

Get a lambda argument from annotation

Assume we have an annotation:
#scala.annotation.meta.field
class MyAnnotation(param: String => String) extends StaticAnnotation
According to Remi T's answer here, if param was just a String, we could extract it this way:
a.tree.children.tail.collect({ case Literal(Constant(id: String)) => id }).headOption
But how can we extract and use a lambda expression? It is a Function(params, body) where params is an arguments list and body is a Tree representing function's body.
It's possible to convert the whole function's Tree to String and then use an interpreter, but it is SO ugly solution (and I couldn't do even this due to some problems with classpath during instantiating the interpreter, none of advices I found worked).

Scala use of underscore as an object placeholder

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.

Syntax for accepting tuple in a function in Scala

I would like a function to consume tuple of 7 but compiler won't let me with the shown message. I failed to find a proper way how to do it. Is it even possible without explicitely typing all the type parameters like Tuple7[String,String...,String] and is it even a good idea to use Scala like this ?
def store(record:Tuple7): Unit = {
}
Error:(25, 20) class Tuple7 takes type parameters
def store(record: Tuple7): Unit = {
^
As stated by Luis you have to define what Type goes on which position for every position in the Tuple.
I`d like to add some approaches to express the same behaviour in different ways:
Tuple Syntax
For that you have two choices, what syntax to use to do so:
Tuple3[String, Int, Double]
(String, Int, Double)
Approach using Case Classes for better readability
Long tuples are hard to handle, especially when types are repeated. Scala offers a different approach for handling this. Instead of a Tuple7 you can use a case class with seven fields. The gain in this approach would be that you now can attach speaking names to each field and also the typing of each position makes more sense if a name is attached to it.
And the chance of putting values in wrong positions is reduced
(String, Int, String, Int)
// vs
case class(name: String, age: Int, taxNumber: String, numberOfChildren: Int)
using Seq with pattern matching
If your intention was to have a sequence of data seq in combination with pattern matching could also be a nice fit:
List("name", 24, "", 5 ) match {
case name:String :: age:Int ::_ :: _ :: Nil => doSomething(name, age)
}
This only works nice in a quite reduced scope. Normally you would lose a lot of type information as the List is of type Any.
You could do the following :
def store(record: (String, String, String, String, String, String, String)):Unit = {
}
which is the equivalent of :
def store(record: Tuple7[String, String, String, String, String, String, String]):Unit = {
}
You can read more about it in Programming in Scala, 2nd Edition, chapter "Next Steps in Scala", sub-chapter "Step 9. use Tuples".