PartialFunction to partially applied function - scala

I'm trying to do the following:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42 = (y: Int) => divide((42, y))
However:
divide42.isDefinedAt(0)
cmd18.sc:1: value isDefinedAt is not a member of Int => Int
val res18 = divide42.isDefinedAt(0)
^Compilation Failed
What is the right way to preserve PartialFunction functionality when going from PartialFunction to partially applied function?

You can use compose to preserve the partial nature:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = divide.compose {
case y: Int => (42, y)
}
divide42.isDefinedAt(0) // false
What you wrote doesn't work because it's actually syntactic sugar for the following:
val divide42 = new Function1[Int, Int] {
def apply(y: Int) = divide((42, y))
}
The call to divide inside divide42 is an expression that evaluates to Int (or throw). There is no way to preserve the fact that divide is a partial function with this syntax.
Or explicitly write a new partial function like this but more verbose:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = {
case (y: Int) if divide.isDefinedAt((42, y)) => divide((42, y))
}
divide42.isDefinedAt(0) // false

Help the compiler help you, define your types explicitly:
EDIT: I realized that simply changing the types results in the y != 0 part of the function not working as intended. compose addresses this as already mentioned in another answer (which is correct).
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if y != 0 => x / y
}
// OLD: val divide42: PartialFunction[Int, Int] = (y: Int) => divide((42, y))
// |- Returns true for `isDefinedAt(0)` which is WRONG!!
// |- If someone could explain why this happens (???), please comment :)
val divide42: PartialFunction[Int, Int] = (y: Int) => divide.compose {
case y: Int => (42, y)
}
divide42.isDefinedAt(0) // False
When you define it as you have, the compiler changes the type of divide42 to Int => Int as opposed to PartialFunction[Int, Int]:
// Implicit type, `Int => Int`
val divide42 = (y: Int) => divide((42, y))
// `isDefinedAt` is not defined for `Int => Int`
divide42.isDefinedAt(0) // !! Error !!

The following seem right to me:
val divide: PartialFunction[(Int, Int), Int] = {
case (x, y) if (y != 0) => x / y
}
val divide42: PartialFunction[Int, Int] = {
case x if (x != 0) => divide(42, x)
}
divide42.isDefinedAt(0) // false
divide42(6) // 7
This both follows the correct definition pattern for PartialFunction and suits the definition of a partially applied function

Related

In the scala function literal, when do I have to use the "case" keyword

I keep stumpling upon this problem and it is annoying (Scala 2.13.4).
case class Coord(x: Int, y: Int)
val data: List[(Int, Int)] = List( (1,2), (3,4) )
data.map{ (x,y) =>
Coord(x,y)
}
gives me this error:
found : (Int, Int) => Coord
required: ((Int, Int)) => Coord
Which I can resolve by adding the "case" keyword
data.map{ case (x,y) =>
Coord(x,y)
}
My question ist when is it mandatory to use the 'case' keyword (here in this specific case and in general). The compiler should already know that it will get a tuple of Int. It seems that most of the time it is not needed. Are there special rules for tuples because they also use parens?
data.map{ case (x,y) =>
Coord(x,y)
}
is equivalent to
data.map { tuple =>
tuple match {
case (x, y) => Coord(x,y)
}
}
Its called pattern matching anonymous function.
It's never mandatory to use case in a function literal.
{ (x, y) => ??? }
defines a function of two arguments, akin to what you'd get from code like
object Foo extends Function2[A, B, C] {
def apply[A, B, C](x: A, y: B): C = ???
}
When passing a tuple, the tuple is passed as a single argument and it then needs to be destructured inside the function. The following are all equivalent ways of destructuring the tuple
{ tuple =>
val (x, y) = tuple
???
}
{ tuple =>
tuple match {
case (x, y) => ???
}
}
{ case (x, y) => ??? }
Note that if you have a function value which takes more than 1 argument, that value has a tupled method which converts a function of n arguments into a function taking a single tuple of n components.
val f = { (x: Int, y: Int) => Coord(x, y) }
// alternatively:
// val f: (Int, Int) => Coord = Coord.apply
val coordinatePairs = List( (1, 2), (3, 4) )
// alternatively:
// val coordinatePairs = List(1 -> 2, 3 -> 4)
coordinatePairs.map(f.tupled)

Filter from Seq less/greater elements and only one equal

I want to implement method in Scala which filters from Seq elements which are for example greater than provided value and additionally returns up to one equal element. For example:
greaterOrEqual(Seq(1,2,3,3,4), 3) shouldBe Seq(3,4)
I ended up with such method:
def greaterOrEqual(
seq: ArrayBuffer[Long],
value: Long
): ArrayBuffer[Long] = {
val greater = seq.filter(_ > value)
val equal = seq.filter(_ == value)
if (equal.isEmpty) {
greater
} else {
equal.tail ++ greater
}
}
but somehow it doesn't look nice to me :) Moreover, I'd like to have generic version of this method where I'd able to use not only Long type but custom case classes.
Do you have any suggestions?
Thanks in advance.
def foo[A : Ordering[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(implicitly[Ordering[A]].gt(_,value))
Or (different style)
def foo[A](seq: Seq[A], value: A)(implicit ord: Ordering[A]) = {
import ord._
seq.find(_ == value).toList ++ seq.filter(_ > value)
}
The code below is deprecated
scala> def foo[A <% Ordered[A]](seq: Seq[A], value: A) = seq.find(_ == value).toList ++ seq.filter(_ > value)
foo: [A](seq: Seq[A], value: A)(implicit evidence$1: A => Ordered[A])List[A]
scala> foo(Seq(1,2,3,3,4,4,5),3)
res8: List[Int] = List(3, 4, 4, 5)
Here's my take on it (preserving original order).
import scala.collection.mutable.ArrayBuffer
def greaterOrEqual[A]( seq :ArrayBuffer[A], value :A
)(implicit ord :Ordering[A]
) : ArrayBuffer[A] =
seq.foldLeft((ArrayBuffer.empty[A],true)){
case (acc, x) if ord.lt(x,value) => acc
case ((acc,bool), x) if ord.gt(x,value) => (acc :+ x, bool)
case ((acc,true), x) => (acc :+ x, false)
case (acc, _) => acc
}._1
testing:
greaterOrEqual(ArrayBuffer.from("xawbaxbt"), 'b')
//res0: ArrayBuffer[Char] = ArrayBuffer(x, w, b, x, t)
This is an excellent problem for a simple tail-recursive algorithm over lists.
def greaterOrEqual[T : Ordering](elements: List[T])(value: T): List[T] = {
import Ordering.Implicits._
#annotation.tailrec
def loop(remaining: List[T], alreadyIncludedEqual: Boolean, acc: List[T]): List[T] =
remaining match {
case x :: xs =>
if (!alreadyIncludedEqual && x == value)
loop(remaining = xs, alreadyIncludedEqual = true, x :: acc)
else if (x > value)
loop(remaining = xs, alreadyIncludedEqual, x :: acc)
else
loop(remaining = xs, alreadyIncludedEqual, acc)
case Nil =>
acc.reverse
}
loop(remaining = elements, alreadyIncludedEqual = false, acc = List.empty)
}
Which you can use like this:
greaterOrEqual(List(1, 3, 2, 3, 4, 0))(3)
// val res: List[Int] = List(3, 4)
You can use the below snippet:
val list = Seq(1,2,3,3,4)
val value = 3
list.partition(_>=3)._1.toSet.toSeq
Here partition method divide the list into two list. First list which satisfy the given condition, and second list contains the remaining elements.
For generic method you can using implicit Ordering. Any type who can compare elements can be handled by greaterOrEqual method.
import scala.math.Ordering._
def greaterOrEqual[T](seq: Seq[T], value: T)(implicit ordering: Ordering[T]): Seq[T] = {
#scala.annotation.tailrec
def go(xs: List[T], value: T, acc: List[T]): List[T] = {
xs match {
case Nil => acc
case head :: rest if ordering.compare(head, value) == 0 => rest.foldLeft(head :: acc){
case (result, x) if ordering.compare(x, value) > 0 => x :: result
case (result, _) => result
}
case head :: rest if ordering.compare(head, value) > 0 => go(rest, value, head :: acc)
case _ :: rest => go(rest, value, acc)
}
}
go(seq.toList, value, List.empty[T]).reverse
}

Implement find and remove in Scala

How is it easier to implement function that find and immutable remove the first occurrence in Scala collection:
case class A(a: Int, b: Int)
val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))
val (s1, r) = s.findAndRemove(_.a == 2)
Result: s1 = Seq(A(1,5), A(4,6), A(5,1), A(2,7)) , r = Some(A(2,3))
It finds the first element that match, and keeps order. It can be improved with List instead of Seq.
case class A(a: Int, b: Int)
val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))
val (s1, r) = s.findAndRemove(_.a == 2)
println(s1)
println(r)
implicit class SeqOps[T](s:Seq[T]) {
def findAndRemove(f:T => Boolean):(Seq[T], Option[T]) = {
s.foldLeft((Seq.empty[T], Option.empty[T])) {
case ((l, None), elem) => if(f(elem)) (l, Option(elem)) else (l :+ elem, None)
case ((l, x), elem) => (l :+ elem, x)
}
}
}
Yeah, a little late to the party, but I thought I'd throw this in.
Minimum invocations of the predicate.
Works with most popular collection types: Seq, List, Array, Vector. Even Set and Map (but for those the collection has no order to preserve and there's no telling which element the predicate will find first). Doesn't work for Iterator or String.
-
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds
implicit class CollectionOps[U, C[_]](xs :C[U]) {
def findAndRemove(p :U=>Boolean
)(implicit bf :CanBuildFrom[C[U], U, C[U]]
,ev :C[U] => collection.TraversableLike[U, C[U]]
) :(C[U], Option[U]) = {
val (before, after) = xs.span(!p(_))
before ++ after.drop(1) -> after.headOption
}
}
usage:
case class A(a: Int, b: Int)
val (as, a) = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7)).findAndRemove(_.a==2)
//as: Seq[A] = List(A(1,5), A(4,6), A(5,1), A(2,7))
//a: Option[A] = Some(A(2,3))
val (cs, c) = Array('g','t','e','y','b','e').findAndRemove(_<'f')
//cs: Array[Char] = Array(g, t, y, b, e)
//c: Option[Char] = Some(e)
val (ns, n) = Stream.from(9).findAndRemove(_ > 10)
//ns: Stream[Int] = Stream(9, ?)
//n: Option[Int] = Some(11)
ns.take(5).toList //List[Int] = List(9, 10, 12, 13, 14)
Try something like this
def findAndRemove(as: Seq[A])(fn: A => Boolean): (Seq[A], Option[A]) = {
val index = as.indexWhere(fn)
if(index == -1) as -> None
else as.patch(index, Nil, 1) -> as.lift(index)
}
val (s1, r) = findAndRemove(s)(_.a == 2)
My version:
def findAndRemove(s:Seq[A])(p:A => Boolean):(Seq[A], Option[A])={
val i = s.indexWhere(p)
if(i > 0){
val (l1, l2) = s.splitAt(i)
(l1++l2.tail, Some(l2.head))
}else{
(s, None)
}
}

Generate prime factors of a number in Scala

How can I generate the factors of an integer in Scala? Here's my take 1:
def factorize(x: Int): List[Int] = {
def foo(x: Int, a: Int): List[Int] = {
if (a > Math.pow(x, 0.5))
return List(x)
x % a match {
case 0 => a :: foo(x / a, a)
case _ => foo(x, a + 1)
}
}
foo(x, 2)
}
factorize(360) // List(2, 2, 2, 3, 3, 5)
Take 2 based on comments from #SpiderPig and #seth-tisue
def factorize(x: Int): List[Int] = {
def foo(x: Int, a: Int): List[Int] = {
(a*a < x, x % a) match {
case (true, 0) => a :: foo(x/a, a)
case (true, _) => foo(x, a+1)
case (false, _) => List(x)
}
}
foo(x, 2)
}
A tail recursive solution:
def factorize(x: Int): List[Int] = {
#tailrec
def foo(x: Int, a: Int = 2, list: List[Int] = Nil): List[Int] = a*a > x match {
case false if x % a == 0 => foo(x / a, a , a :: list)
case false => foo(x , a + 1, list)
case true => x :: list
}
foo(x)
}
Just little improvement of "Take 2" from the question:
def factorize(x: Int): List[Int] = {
def foo(x: Int, a: Int): List[Int] = x % a match {
case _ if a * a > x => List(x)
case 0 => a :: foo(x / a, a)
case _ => foo(x, a + 1)
}
foo(x, 2)
}
Also, the following method may be a little faster (no x % a calculation in the last iteration):
def factorize(x: Int): List[Int] = {
def foo(x: Int, a: Int): List[Int] = if (a * a > x) List(x) else
x % a match {
case 0 => a :: foo(x / a, a)
case _ => foo(x, a + 1)
}
foo(x, 2)
}

How to declare implicit arguments in higher order functions?

I want IMPLICIT args in a higher order function, like:
func(arg1) { implicit (x, y) => x * y }
But the compiler says:
error: expected start of definition
val a = func("2", "4") { implicit (x, y) =>
^
java version "1.7.0_40"
Scala code runner version 2.10.2-RC2 -- Copyright 2002-2013, LAMP/EPFL
The runnable sample code:
object Test extends App {
new Test().run
}
class Test {
def run = {
val a = func("2", "4") { (x, y) => // It's OK
x * y
}
println("a: " + a)
val b = gunc("2", "4") { implicit x => { implicit y => // It's OK
x * y
}}
println("b: " + b)
}
def func(x: String, y: String)(f: (Int, Int) => Int) = f(x.toInt, y.toInt)
def gunc(x: String, y: String)(g: Int => Int => Int) = g(x.toInt)(y.toInt)
def hunc(x: String, y: String)(h: Tuple2[Int, Int] => Int) = h((x.toInt, y.toInt))
}
[ADD COMMENT]
I wonder...
We can declare as "implicit x => ..." with one arg.
It seems there is no way to declare two implicit args.
Try adding:
val c = hunc("2", "4") { implicit pair => pair._1 * pair._2 }
When you say implicit y => y * 2 you're not
declaring an implicit argument but mark the function as implicit,
so you make an analog to this:
implicit val f1 = (y: Int) => y * 2
def func1(x: String, y: String)(f: Int => Int) = f(1)
func1("", "")(f1)
When you want to mark a function with two
arguments as implicit you can do it this way:
implicit val f2 = (x: Int, y: Int) => y * 2
def func2(x: String, y: String)(f: (Int, Int) => Int) = f(1, 2)
func2("", "")(f2)
But you cannot do it so:
func2("", "")(implicit (x, y) => x), in this particular case I just don't see any meaning to use implicits.
Also you can see this question, maybe you'll find some useful information there