def readf(value_name: String, operator:operand, compared_value:Int f:()=>Unit) {
I want to look up an Int in a HashMap based on the value_name String passed in. Taking that value I want to compare it
value operator compared_value
if that statement is true I want to execute f.
How do I pass in a comparator and evaluate this logic? Preferably without writing my own classes.
The result from the HashMap can be as an Option which you can then filter with the operand/compared_value. Then it should be just a map on the resulting option. It would look something like:
yourMap.get(value_name).filter(_ operator compared_value).map(f)
This does assume that operator is (Int, Int) => Boolean as asked in the comment
It's kind of hard to help with the editorial issues your question has, but I'll try. Assuming you have a myMap: Map[String, Int] in scope (which your question does not show) and assuming your operator is really of type (Int, Int) => Boolean, you could do:
scala> val myMap = Map("test" -> 8)
myMap: scala.collection.immutable.Map[String,Int] = Map(test -> 8)
scala> :paste
// Entering paste mode (ctrl-D to finish)
def readf(value_name: String, operator: (Int, Int) => Boolean, compared_value:Int, f:()=>Unit) {
myMap.get(value_name).filter(operator(_, compared_value)).foreach(_ => f())
}
// Exiting paste mode, now interpreting.
readf: (value_name: String, operator: Int => (Int => Boolean), compared_value: Int, f: () => Unit)Unit
scala> val eqComparator = ((_: Int) == (_: Int))
eqComparator: (Int, Int) => Boolean = <function2>
scala> val f = () => println("success")
f: () => Unit = <function0>
scala> readf("test", eqComparator, 8, f)
success
scala> readf("test", eqComparator, 5, f)
scala> readf("other", eqComparator, 8, f)
(Edited to remove the curried operator. It's probably clearer this way.)
Related
I tried to use zip and map to create zipwith function like:
def zipWithArray(f : (Int, Int) => Int)(xs : Array[Int], ys: Array[Int]) : Array[Int] = xs zip ys map f
But I got the following compile error:
type mismatch;
found : (Int, Int) => Int
required: ((Int, Int)) => ?
I know the zip is (Array[Int], Array[Int])=>Array((Int, Int)), so the f should be (Int, Int) => Int and the total result is Array[Int]. Could anyone help to explain the case please. Thanks a lot.
(Int, Int) => Int is function which takes two Int as argument.
((Int, Int)) => ? is function which takes one tuple which consists of two Int as argument.
Since xs zip ys is array of tuple, what you need is function which takes tuple as argument and returns Int.
So xz zip ys map f.tupled should work.
Reference: How to apply a function to a tuple?
It's pretty much as the error message states; change your function signature to:
def zipWithArray(f : ((Int, Int)) => Int)(xs : Array[Int], ys: Array[Int])
Without the extra parentheses, f looks like a function that takes two integers, rather than a function that takes a tuple.
Convert the function to accept arguments as tuples and then map can be used to call the function.
For example :
scala> def add(a : Int, b: Int) : Int = a + b
add: (a: Int, b: Int)Int
scala> val addTuple = add _ tupled
<console>:12: warning: postfix operator tupled should be enabled
by making the implicit value scala.language.postfixOps visible.
This can be achieved by adding the import clause 'import scala.language.postfixOps'
or by setting the compiler option -language:postfixOps.
See the Scaladoc for value scala.language.postfixOps for a discussion
why the feature should be explicitly enabled.
val addTuple = add _ tupled
^
addTuple: ((Int, Int)) => Int = scala.Function2$$Lambda$224/1945604815#63f855b
scala> val array = Array((1, 2), (3, 4), (5, 6))
array: Array[(Int, Int)] = Array((1,2), (3,4), (5,6))
scala> val addArray = array.map(addTuple)
addArray: Array[Int] = Array(3, 7, 11)
I want to write a simple method that takes a function as a parameter and then executes it.
def exec(f: (a:Int, b:Int) => Boolean): Boolean = f(a,b)
I'm not sure what is wrong with the above, but I get the error:
<console>:1: error: ')' expected but ':' found.
def exec(f: (a:Int, b:Int) => Boolean): Boolean = f(a,b)
^ ^
| |
// These are supposed to be types, but a: Int and b: Int aren't types,
// they are identifiers with type ascriptions.
It should look a little more like:
def exec(f: (Int, Int) => Boolean): Boolean = f(a, b)
Now f is a function (Int, Int) => Boolean. But this doesn't compile, because a and b are not defined.
You either need to pass them in, or fix them to a value.
def exec(a: Int, b: Int)(f: (Int, Int) => Boolean): Boolean = f(a, b)
scala> exec(2, 3)(_ > _)
res1: Boolean = false
If you want to execute a function with parameters in your exec method you need to:
scala> def exec(f: => Unit) = {
| println("Exec:")
| f
| }
scala> def foo(f : (Int, Int)): Unit = println(f._1 + f._2)
scala> exec(foo((3, 4)))
Exec:
7
because foo((3, 4)) type is => Unit
Not quite an answer to your original question (and too big to be a comment), but if you're looking to write a tasteful, nice-looking execution operator and don't particularly like the syntax of the provided answers, perhaps something similar to scalaz's pipe operator (|>) might be what you're thinking of?
scala> // You could just get this from scalaz with import scalaz._ and import Scalaz._
scala> implicit class FancyExec[A](x: A){def |>[B](f: A => B) = f(x)}
scala> 5 |> (_ + 6)
res1: Int = 11
scala> (5, 4) |> ((_: Int) < (_: Int)).tupled
res2: Boolean = false
scala> val f = ((_: Int) < (_: Int)).tupled
f: ((Int, Int)) => Boolean = <function1>
scala> val g = ((_: Int) > (_: Int)).tupled
g: ((Int, Int)) => Boolean = <function1>
scala> List(f, g) map ((5, 4) |> _)
res3: List[Boolean] = List(false, true)
There are some discussions here about this, but I have some specific questions I wasn't able to find an answer for. So, by call-by-name, I mean =>T type, and by 0-arity function I mean () => T
I understand (I think) the conceptual difference, but probably I am missing something as I still have lots of questions:
Why do we have the concept of =>T at all if we could always use () => T?
Is there any syntax/functional limitations of each? For now I found only that => cannnot be used as a class field. Is this the only limitation?
Is the generated code always the same for both?
Should I always prefer =>T? And why?
Is it correct to call =>T a type? It looks for me like it does not have any type representation in scala.
1) It's just more handy to use it, especially inside DSLs:
def printAndGet[T](f: => T) = {
val res = f
println(res + " printed")
res
}
scala> :paste
// Entering paste mode (ctrl-D to finish)
val k = printAndGet {
val a = 5
5 * a
}
// Exiting paste mode, now interpreting.
25 printed
k: Int = 25
2) => T can only be a parameter of method or function. And actually => T and () => T aren't interchangable:
scala> def aaa(f: => String) = f
aaa: (f: => String)String
scala> val a: Function1[() => String, String] = aaa _
<console>:8: error: type mismatch;
found : (=> String) => String
required: (() => String) => String
val a: Function1[() => String, String] = aaa _
^
Thanks to #som-snytt, fоund this one:
scala> object O { def f(i: Int) = i; def f(i: => Int) = i + 1 }
defined object O
scala> O.f(5)
res12: Int = 5
scala> O.f(5: (=> Int))
<console>:1: error: no by-name parameter type allowed here
O.f(5: (=> Int))
^
Even this which should work if it compiles - but it doesn't (scala 2.11.2, 2.11.5 REPL just crashes):
scala> val k: (=> Int) => Int = O.f _
k: (=> Int) => Int = <function1>
scala> k(5) //should be 6
res18: Int = 5 //WTF?
Last one seems like a bug
3) Not exactly, if you want the same, just convert => T into () => T:
scala> def aaa(f: => String) = {f _}
aaa: (f: => String)() => String
Bytecode may also differ. For instance, compiler will more likely inline code from => T without generating lambda for it. So, the key difference is that () => T is actually an object (first class citizen), => T isn't.
4) see 1, but sometimes you may need to ensure that user knows that computation might be delayed - () => T is better then.
5) It's part of a type signature, just look at eta-expansion of:
scala> def aaa(f: => String) = {f}
aaa: (f: => String)String
scala> aaa _ //convert method into a function
res7: (=> String) => String = <function1>
scala> val a: ( => String) => String = aaa _
a: (=> String) => String = <function1>
However scala doesn't recognize it as independent type:
scala> val a: Function1[( => String), String] = aaa _
<console>:1: error: no by-name parameter type allowed here
val a: Function1[( => String), String] = aaa _
^
val list = List((1,2), (3,4))
list.map(tuple => {
val (a, b) = tuple
do_something(a,b)
})
// the previous can be shortened as follows
list.map{ case(a, b) =>
do_something(a,b)
}
// similarly, how can I shorten this (and avoid declaring the 'tuple' variable)?
def f(tuple: (Int, Int)) {
val (a, b) = tuple
do_something(a,b)
}
// here there two ways, but still not very short,
// and I could avoid declaring the 'tuple' variable
def f(tuple: (Int, Int)) {
tuple match {
case (a, b) => do_something(a,b)
}
}
def f(tuple: (Int, Int)): Unit = tuple match {
case (a, b) => do_something(a,b)
}
Use tupled
scala> def doSomething = (a: Int, b: Int) => a + b
doSomething: (Int, Int) => Int
scala> doSomething.tupled((1, 2))
res0: Int = 3
scala> def f(tuple: (Int, Int)) = doSomething.tupled(tuple)
f: (tuple: (Int, Int))Int
scala> f((1,2))
res1: Int = 3
scala> f(1,2) // this is due to scala auto-tupling
res2: Int = 3
tupled is defined for every FunctionN with N >= 2, and returns a function expecting the parameters wrapped in a tuple.
While this might look like a trivial suggestion, the f function, can be further simplified by just using _1 and _2 on a tuple.
def f(tuple: (Int, Int)): Unit =
do_something(tuple._1, tuple._2)
Obviously by doing this you're affecting readability (some meta-information about the meaning of the 1st and 2nd parameter of the tuple is removed) and should you wish to use elements of the tuple somewhere else in the f method you will need to extract them again.
Though for many uses this might be still the easiest, shortest and most intuitive alternative.
If I understand correctly you are trying to pass a tuple to a method with 2 args?
def f(tuple: (Int,Int)) = do_something(tuple._1, tuple._2)
by more readable, I mean giving variable names instead of using the _1 an _2 on the tuple
In this case, it's a good idea to use a case class instead of a tuple, especially since it only takes one line:
case class IntPair(a: Int, b: Int)
def f(pair: IntPair) = do_something(pair.a, pair.b)
If you get (Int, Int) from external code which can't be changed (or you don't want to change), you could add a method converting from a tuple to IntPair.
Another option: {(a: Int, b: Int) => a + b}.tupled.apply(tuple). Unfortunately, {case (a: Int, b: Int) => a + b}.apply(tuple) doesn't work.
I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.
def foo(a:Int, b:Int) = {}
foo(a,b) //right way to invoke foo
foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??
def getParams = {
//Some calculations
(a,b) //where a & b are Int
}
It's a two step procedure. First turn foo into a function, then call tupled on it to make it a function of a tuple.
(foo _).tupled(getParams)
#dave-griffith is dead on.
You can also call:
Function.tupled(foo _)
If you want to wander into "way more information than I asked for" territory, there are also methods built into partially applied functions (and on Function) for currying. A few input/output examples:
scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double
scala> foo _
res0: (Int, Double) => Double = <function2>
scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>
scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>
scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>
// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>
Wherein the curried version is invoked with multiple argument lists:
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> c(5)
res13: (Double) => Double = <function1>
scala> c(5)(10)
res14: Double = 50.0
Finally, you can also uncurry/untuple if needed. Function has builtins for this:
scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>
scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Function.tupled(foo _)(getParams) or the one suggested by Dave.
EDIT:
To respond to your comment:
What if foo happens to be the
constructor of some class?
In that case, this trick won't work.
You can write a factory method in the companion object of your class and then obtain the tupled version of its apply method using one of the aforementioned techniques.
scala> class Person(firstName: String, lastName: String) {
| override def toString = firstName + " " + lastName
| }
defined class Person
scala> object Person {
| def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
| }
defined module Person
scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G
With case classes you get a companion object with an apply method for free, and thus this technique is more convenient to use with case classes.
scala> case class Person(firstName: String, lastName: String)
defined class Person
scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)
I know that's a lot of code duplication but alas... we don't have macros (yet)! ;)
I appreciate some of the other answers which were closer to what you asked for, but I found it easier for a current project to add another function which converts tuple parameters into the split parameters:
def originalFunc(a: A, b: B): C = ...
def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
Now, you can implement foo and make it take a param of the Tuple2 class like so.
def foo(t: Tuple2[Int, Int]) = {
println("Hello " + t._1 + t._2)
"Makes no sense but ok!"
}
def getParams = {
//Some calculations
val a = 1;
val b = 2;
(a, b) //where a & b are Int
}
// So you can do this!
foo(getParams)
// With that said, you can also do this!
foo(1, 3)