1

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?

0

3 Answers 3

4

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 
Sign up to request clarification or add additional context in comments.

3 Comments

@SergeyBushmanov added a bit of comment
@GaëlJ well put, makes sense to me, tyvm :)
You're invited to compare yours and mine below.
0

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 !! 

7 Comments

isDefinedAt(0) \\ true was wrong indeed. But now we're back to what already was answered 10 hours ago. The original version was kneat but doesn't work as intended. Why?
@SergeyBushmanov that is a good question, one I have as well; doesn't seem intuitive to me, but as currently written, it should work as intended
It's more of a question "why?" than "what just works". Ascribing the right type seem to be the step in the right direction. But how make it work? And why compose ???
Your "old" PartialFunction is defined for the input 0. It is actually defined for every Int. See my answer updated with a comment to help understand why.
@GaëlJ could you clarify on how isDefinedAt(0) is synthesized? That it accepts 0 doesn't make sense still actually
|
0

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

3 Comments

Drawback of this is that you are repeating the condition (x != 0) in both functions. With compose you don't need to know at which input the first function is defined.
@GaëlJ I do not see this as a drawback until you disclose how compose overcomes this
By this definition of isDefinedAt for the composed function: github.com/scala/scala/blob/v2.13.5/src/library/scala/… (you can also look at def compose to see it returns a Combined.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.