12

I just wanted to clarify something about partially defined functions in Scala. I looked at the docs and it said the type of a partial function is PartialFunction[A,B], and I can define a partial function such as

val f: PartialFunction[Any, Int] = {...} 

I was wondering, for the types A and B, is A a parameter, and B a return type? If I have multiple accepted types, do I use orElse to chain partial functions together?

1
  • 1
    Yes, that's the right idea. Commented Aug 19, 2015 at 1:22

3 Answers 3

11

In the set theoretic view of a function, if a function can map every value in the domain to a value in the range, we say that this function is a total function. There can be situations where a function cannot map some element(s) in the domain to the range; such functions are called partial functions.

Taking the example from the Scala docs for partial functions:

val isEven: PartialFunction[Int, String] = { case x if x % 2 == 0 => x+" is even" } 

Here a partial function is defined since it is defined to only map an even integer to a string. So the input to the partial function is an integer and the output is a string.

val isOdd: PartialFunction[Int, String] = { case x if x % 2 == 1 => x+" is odd" } 

isOdd is another partial function similarly defined as isEven but for odd numbers. Again, the input to the partial function is an integer and the output is a string.

If you have a list of numbers such as:

List(1,2,3,4,5) 

and apply the isEven partial function on this list you will get as output

List(2 is even, 4 is even) 

Notice that not all the elements in the original list have been mapped by the partial function. However, there may be situations where you want to apply another function in those cases where a partial function cannot map an element from the domain to the range. In this case we use orElse:

val numbers = sample map (isEven orElse isOdd) 

And now you will get as output:

List(1 is odd, 2 is even, 3 is odd, 4 is even, 5 is odd) 
Sign up to request clarification or add additional context in comments.

2 Comments

what exactly you mean by apply the isEven function. If it means map "List(1, 2, 3, 4, 5) map isEven" it will result in scala.MatchError: 1 (of class java.lang.Integer)
@AbhishekGayakwad, no. You have to use collect in that case. You cannot use map since it will fail for the odd number obviously. collect checks first using the isDefinedAt function.
4

If you are looking to set up a partial function that, in effect, takes multiple parameters, define the partial function over a tuple of the parameters you'll be feeding into it, eg:

val multiArgPartial: PartialFunction[(String, Long, Foo), Int] = { case ("OK", _, Foo("bar", _)) => 0 // Use underscore to accept any value for a given parameter } 

and, of course, make sure you pass arguments to it as tuples.

Comments

0

In addition to other answers, if by "multiple accepted types" you mean that you want the same function accept e.g. String, Int and Boolean (and no other types), this is called "union types" and isn't supported in Scala currently (but is planned for the future, based on Dotty). The alternatives are:

  1. Use the least common supertype (Any for the above case). This is what orElse chains will do.
  2. Use a type like Either[String, Either[Int, Boolean]]. This is fine if you have two types, but becomes ugly quickly.
  3. Encode union types as negation of intersection types.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.