This is a Scala-specific question.
Assume that you have a function (which you cannot modify) of several inputs, e.g.:
def test(x1: Int, x2:Int, x3: Int, x4: Int, x5: Int) = {
//Some logic
}
And assume that you have all the inputs for that function in a single array, e.g.:
val inputs = Array(1, 2, 3, 4, 5)
Is there a way to call test with that single array of inputs without explicitly inserting individual array elements (as in test(inputs(0),inputs(1),inputs(2),inputs(3),inputs(4)))?
This is particularly important for the case when I don't know the number of inputs and the number of elements in the array in advance (but know that they match).
No that's not possible. It's possible to use an array for a function that expects varargs by using :_* syntax. Also, your question is contradictory:
the case when I don't know the number of inputs and the number of
elements in the array in advance (but know that they match)
How could you not know the number of inputs or elements but know they match?
You can curry the function and then use one of the solutions proposed here.
For instance, using this technique:
class Acc[T](f: Function1[T, _]) {
private[this] var ff: Any = f
def apply(t: T): this.type = {
ff = ff.asInstanceOf[Function1[T,_]](t)
this
}
def get = ff match {
case _: Function1[_,_] => sys.error("not enough arguments")
case res => res.asInstanceOf[T]
}
}
def test(x1: Int, x2:Int, x3: Int, x4: Int, x5: Int) = {
//Some logic
}
val inputs = Array(1, 2, 3, 4, 5)
inputs.foldLeft(new Acc((test _).curried))((acc, i) => acc(i)).get
Not extremely safe, but it should work
You can use Java reflection (or Scala reflection, but Java's one is sufficient for this). The below is a quick and dirty solution, which assumes you have a class Test which contains exactly one test method:
val m = classOf[Test].
getMethods.find(_.getName == "test").
getOrElse(throw new Exception("No method called test"))
// inputs must be Array[Object], not Array[Int] as in your example
m.invoke(instanceOfTest, inputs)
This is rarely a good idea, however.
Related
I've got functions with following signatures:
case class Sth(index: Long, str: String)
def fetch(n: Long): F[Sth] = ??? //implemented
def findFirstAndLast(min: Long, max: Long, str: String): F[(Long, Long)] = ???
I have certainty that str are grouped and groups don't occur twice.
For example this will be correct:
Sth(1, "a")
Sth(2, "a")
Sth(3, "b")
Sth(4, "b")
Sth(5, "b")
Sth(6, "c")
Sth(7, "d")
Sth(8, "d")
and that should be result of my function: findFirstAndLast(1, 8, "b") = F((3, 5))
But following case will never happen:
Sth(1, "a")
Sth(2, "b")
Sth(3, "b")
Sth(4, "a")
I tried to implement this but my brain stopped functioning when I've added the effect.
Start by envisioning your algorithm as a recursive one, where there is some initial "state", and the algorithm can choose at each step to either update the state and recurse, or finish with a result.
You could represent your state as
case class State(index: Long, firstMatch: Option[Long])
where the index is the current index you are about to inspect, and the firstMatch is the index where you found your first matching string.
At each step, the algorithm will look at the index and check whether it is in-bounds compared to the max. If it's out of bounds, it must exit with whatever values it found. If it's in-bounds, grab the string associated with that index, then based on whether that string matches and whether you already found your firstMatch, decide whether to continue checking at the next index or return a result.
In order to perform recursion with effects, you're going to need a Monad[F]. You can find a lot of articles that explain what a Monad is, but to simplify for the purposes of this answer, it's a thing that knows how to flatMap your F, and provides the handy tailRecM function for doing that flatMapping recursively.
tailRecM is a way to represent a recursive algorithm with an F[_] effect.
def tailRecM[A, B](a: A)(f: (A) ⇒ F[Either[A, B]]): F[B]
The a: A is your initial state, e.g. State(min, None)
The f: A => F[Either[A, B]] is a function that inspects your current state, then decides whether to recurse, where that decision is done inside an F effect. Basically Left means recurse, Right means exit. It's perfect for your situation, where you have a fetch method that forces you into an F effect.
It returns an F[B] when your f returns an F[Right[B]], i.e. the end of recursion.
When you write your method, you just have to make sure there is a Monad available for the F type you're using, so you can use it to call tailRecM. In my demo, I put F as a type parameter on the method and made fetch into an argument, but I suspect in your code, both findFirstAndLast and fetch are defined inside some class that has the F type parameter. Adjust as necessary.
def findFirstAndLast[F[_]: Monad](
min: Long,
max: Long,
str: String,
fetch: Long => F[String],
)(implicit F: Monad[F]): F[Option[(Long, Long)]] =
F.tailRecM(State(min, None)) {
// if out of bounds, result is None if firstIndex was never found,
// or `firstIndex -> max` if it was found
case State(index, firstIndex) if index > max =>
// note: `f` wants an `F[Either[..]]` so we wrap the either with `F.pure`
F.pure(Right(firstIndex.map(_ -> max)))
// if in-bounds, fetch the index and decide from there
case State(index, firstMatch) =>
F.map(fetch(index)) {
case `str` if firstMatch.isEmpty =>
// found the first match!
Left(State(index + 1, Some(index)))
case `str` if firstMatch.isDefined =>
// still matching after first
Left(State(index + 1, firstMatch))
case other if firstMatch.isDefined =>
// no longer matching, last match must be previous step
Right(Some((firstMatch.get, index - 1)))
case other =>
// still looking for first match
Left(State(index + 1, None))
}
}
Example usage with F=SyncIO, but this will work generally with any F type that has a Monad, e.g. IO, monix.eval.Task, Future, Option, etc.
def exampleFetch(n: Long) = SyncIO { "aabbbcdd".charAt(n.toInt - 1).toString }
val result = findFirstAndLast(1, 8, "b", exampleFetch).unsafeRunSync()
println(result) // Some((3, 5))
https://scastie.scala-lang.org/oN0P6e3JQ7WEKkgbxuPLuQ
I am trying to get the sum of arguments using currying in Scala. This is a very basic question so please don't go hard on it.
If you can answer the question then please otherwise let it be:
object MultiSum extends App {
var res=0
def sum(f:Int=>Int)(x:Int*)={f(x)}
val a=List(1,2,3,4,5,6,7,8,9)
val b=sum(x=>x+x)(a:_*)
}
So val b will be storing the result of all the numbers passed in the List in var a
Thanks.
Well... first of all... I think you should call your function collect and not sum. Now, lets help you write this collect.
So... your collect function takes two arguments,
1 - A collector function.
2 - Things to accumulate.
So... your collector function needs to know two things... first is already collected and second is next item to collect... and it will produce the next collected.
Which means that for collection of Int, your collector function will have a signature (Int, Int) => Int.
So, your collect function should have following signature,
def collect(collector: (Int, Int) => Int)(items: Int*): Int = ???
Now... lets come to implement it.
1 - Using reduce
def collect(collector: (Int, Int) => Int)(items: Int*): Int =
items.reduce(collector)
2 - Using fold
def collect(collector: (Int, Int) => Int)(items: Int*): Int =
items.fold(0)(collector)
Now, you can use it like this,
val l = List(1,2,3,4,5,6,7,8,9)
val b = collect((i1, i2) => i1 + i2)(l: _*)
I'd like to write a generic loop until a given condition stands, in a functional way.
I've came up with the following code :
def loop[A](a: A, f: A => A, cond: A => Boolean) : A =
if (cond(a)) a else loop(f(a), f, cond)
What are other alternatives ? Is there anything in scalaz ?
[update] It may be possible to use cats and to convert A => A into Reader and afterwards use tailRecM. Any help would be appreciated.
I agree with #wheaties's comment, but since you asked for alternatives, here you go:
You could represent the loop's steps as an iterator, then navigate to the first step where cond is true using .find:
val result = Iterator.iterate(a)(f).find(cond).get
I had originally misread, and answered as if the cond was the "keep looping while true" condition, as with C-style loops. Here's my response as if that was what you asked.
val steps = Iterator.iterate(a)(f).takeWhile(cond)
If all you want is the last A value, you can use steps.toIterable.last (oddly, Iterator doesn't have .last defined). Or you could collect all of the values to a list using steps.toList.
Example:
val steps = Iterator.iterate(0)(_ + 1).takeWhile(_ < 10)
// remember that an iterator is read-once, so if you call .toList, you can't call .last
val result = steps.toIterable.last
// result == 9
From your structure, I think what you are describing is closer to dropWhile than takeWhile. What follows is 100% educational and I don't suggest that this is useful or the proper way to solve this problem. Nevertheless, you might find it useful.
If you want to be generic to any container (List, Array, Option, etc.) You will need a method to access the first element of this container (a.k.a. the head):
trait HasHead[I[_]]{
def head[X](of: I[X]): X
}
object HasHead {
implicit val listHasHead = new HasHead[List] {
def head[X](of: List[X]) = of.head
}
implicit val arrayHasHead = new HasHead[Array] {
def head[X](of: Array[X]) = of.head
}
//...
}
Here is the generic loop adapted to work with any container:
def loop[I[_], A](
a: I[A],
f: I[A] => I[A],
cond: A => Boolean)(
implicit
hh: HasHead[I]): I[A] =
if(cond(hh.head(a))) a else loop(f(a), f, cond)
Example:
loop(List(1,2,3,4,5), (_: List[Int]).tail, (_: Int) > 2)
> List(3, 4, 5)
I have something like this:
def fnA(argA: Int, argB: Int, argC: Int): Seq[Int] = {
tryRequest {
...
}
}
def tryRequest[T](f: => T): T = {
try {
f
} catch {
...
}
}
I'm trying to figure out how to test this with Mockito/ScalaTest. I want to either make sure that 1. my return type is what I expect it to be (Seq[Int] when I call fnA), or 2. that I am passing in the right type to tryRequest when I'm calling it ((Int, Int, Int) => Seq[Int] when I call fnA). I've tried variations of:
exampleInstance.fnA(1, 2, 3)
there was one(exampleInstance).tryRequest(any)
but I always get something like
Argument(s) are different! Wanted:
exampleInstance.tryRequest(
($anonfun$apply$17) <function0>
);
Actual invocation has different arguments:
exampleInstance.tryRequest(
($anonfun$fnA$1) <function0>
);
Any ideas how I can accurately test this? Thanks!
It's not entirely clear what you're passing where - you seem to think you're passing a (Int, Int, Int) => Seq[Int] to tryRequest, but the definition of fnA you give isn't doing that (it's already taken the Int arguments before it calls tryRequest). But going by what you've written rather than the code:
It's generically impossible to compare functions for equality, and that syntax will "really" create an anonymous wrapper (do you really need the laziness of the => T given that you're passing a function in there anyway?), thus the failures. What you can do is confirm that the function that was passed to the inner call has some of the same properties as the function you already passed. I don't know the fancy syntax, but with an ordinary Java testing/mocking library I'd do something like:
val myCaptor = capture[=> ((Int, Int, Int) => Seq[Int])]
expect(exampleInstance.tryRequest(myCaptor.capture()))
exampleInstance.fnA({(a, b, c) => a + b + c})
val functionThatWasPassed = myCaptor.getValue()
assertThat(functionThatWasPassed(3, 4, 5)) isEqualTo 12
assertThat(functionThatWasPassed(-1, 0, 2)) isEqualTo 1
Say I have the following data structure:
case class Timestamped[CC[M] < Seq[M]](elems : CC, timestamp : String)
So it's essentially a sequence with an attribute -- a timestamp -- attached to it. This works fine and I could create new instances with the syntax
val t = Timestamped(Seq(1,2,3,4),"2014-02-25")
t.elems.head // 1
t.timestamp // "2014-05-25"
The syntax is unwieldly and instead I want to be able to do something like:
Timestamped(1,2,3,4)("2014-02-25")
t.head // 1
t.timestamp // "2014-05-25"
Where timestamped is just an extension of a Seq and it's implementation SeqLike, with a single attribute val timestamp : String.
This seems easy to do; just use a Seq with a mixin TimestampMixin { val timestamp : String }. But I can't figure out how to create the constructor. My question is: how do I create a constructor in the companion object, that creates a sequence with an extra member value? The signature is as follows:
object Timestamped {
def apply(elems: M*)(timestamp : String) : Seq[M] with TimestampMixin = ???
}
You'll see that it's not straightforward; collections use Builders to instantiate themselves, so I can't simply call the constructor an override some vals.
Scala collections are very complicated structures when it comes down to it. Extending Seq requires implementing apply, length, and iterator methods. In the end, you'll probably end up duplicating existing code for List, Set, or something else. You'll also probably have to worry about CanBuildFroms for your collection, which in the end I don't think is worth it if you just want to add a field.
Instead, consider an implicit conversion from your Timestamped type to Seq.
case class Timestamped[A](elems: Seq[A])(timestamp: String)
object Timestamped {
implicit def toSeq[A](ts: Timestamped[A]): Seq[A] = ts.elems
}
Now, whenever I try to call a method from Seq, the compiler will implicitly convert Timestamped to Seq, and we can proceed as normal.
scala> val ts = Timestamped(List(1,2,3,4))("1/2/34")
ts: Timestamped[Int] = Timestamped(List(1, 2, 3, 4))
scala> ts.filter(_ > 2)
res18: Seq[Int] = List(3, 4)
There is one major drawback here, and it's that we're now stuck with Seq after performing operations on the original Timestamped.
Go the other way... extend Seq, it only has 3 abstract members:
case class Stamped[T](elems: Seq[T], stamp: Long) extends Seq[T] {
override def apply(i: Int) = elems.apply(i)
override def iterator = elems.iterator
override def length = elems.length
}
val x = Stamped(List(10,20,30), 15L)
println(x.head) // 10
println(x.timeStamp) // 15
println(x.map { _ * 10}) // List(100, 200, 300)
println(x.filter { _ > 20}) // List(30)
Keep in mind, this only works as long as Seq is specific enough for your use cases, if you later find you need more complex collection behavior this may become untenable.
EDIT: Added a version closer to the signature you were trying to create. Not sure if this helps you any more:
case class Stamped[T](elems: T*)(stamp: Long) extends Seq[T] {
def timeStamp = stamp
override def apply(i: Int) = elems.apply(i)
override def iterator = elems.iterator
override def length = elems.length
}
val x = Stamped(10,20,30)(15L)
println(x.head) // 10
println(x.timeStamp) // 15
println(x.map { _ * 10}) // List(100, 200, 300)
println(x.filter { _ > 20}) // List(30)
Where elems would end up being a generically created WrappedArray.