9

Since a total function is a special case of a partial function, I think I should be able to return a function when I need a partial.

Eg,

def partial : PartialFunction[Any,Any] = any => any

Of course this syntax fails to compile. My question is, is it possible to do this, and if so what do I need to do to get the syntax right.

I know I can do the following, but this is just an out-of-curiousity-question

def partial : PartialFunction[Any,Any] = {
  case any => any
}
duplode
  • 33,731
  • 7
  • 79
  • 150
sksamuel
  • 16,154
  • 8
  • 60
  • 108
  • 1
    Note that there is a `PartialFunction.apply` method: `def partial = PartialFunction[Any,Any]{ any => any }` – senia Jan 02 '14 at 20:20
  • 1
    @senia, you should enter your comment as the answer as I believe it's correct and should be what the op is looking for – cmbaxter Jan 02 '14 at 20:26

5 Answers5

12

You could use PartialFunction.apply method:

val partial = PartialFunction[Any,Any]{ any => any }

You could import this method if you want to make it shorter:

import PartialFunction.{apply => pf}
val partial = pf[Any,Any]{ any => any }
senia
  • 37,745
  • 4
  • 88
  • 129
  • I'm going to upvote this because I did not know you could do that, but it's still not quite what I was hoping for. I think this is probably more work than just doing { case any => any } right. This apply is probably very useful when you already have a function rather than defining inline I guess. – sksamuel Jan 02 '14 at 20:35
  • I always try and use language features if they fit my needs first before writing my own code instead. I guess you just need to determine if this fits your needs or not... – cmbaxter Jan 02 '14 at 20:38
  • I don't really have any needs in this case (excuse the pun :)). I was just writing a partial function today that simply returned the input, and I thought an inline total function would have been nice. I ended up doing case { any => any} but I would it would make a good SO question. – sksamuel Jan 02 '14 at 20:39
  • 1
    @monkjack: You'll use it in case if you already have a function (`PartialFunction{identity}`) or if you want to use it as part of expression: `partail orElse pf(identity)`. – senia Jan 02 '14 at 20:40
  • hi, I know it's an old question, but could anyone come up with a reason of NOT having that conversion available implicitly? So if I have sth like that in scope `implicit def lift[I, O](f: Function1[I,O]): PartialFunction[I,O] = PartialFunction(f)`. Could I shoot myself in the foot with this? – agilesteel Nov 15 '17 at 15:13
  • As of **Scala 2.13.5** a `PartialFunction.fromFunction(identity[String] _)` will do the trick whilst `PartialFunction(identity)` results in `PartialFunction.type does not take parameters`. – phdoerfler Apr 12 '21 at 11:45
  • A more concise way that works for **Scala 2.13.5** is `(identity[String] _): PartialFunction[String, String]` or `(identity[String] _): String =/> String` if you `import scala.{PartialFunction => =/>}` – phdoerfler Apr 12 '21 at 12:22
4

A FunctionN is not a total function:

val evilFun: Int => Int = n => if (n < 0) sys.error("I'm evil!") else n

In other words, all Scala functions are partial functions. Therefore PartialFunction just gives you a way to inspect the partial function via isDefinedAt and chain partial functions via orElse.

It could make sense to get rid of PartialFunction altogether and have isDefinedAt at the level of FunctionN with function literals and lifted methods implementing isDefinedAt as always true.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Heiko Seeberger
  • 3,702
  • 21
  • 20
1

I think you may have the concept switched.

PartialFunction[-A, +B] extends (A) ⇒ B 

However, you can't use a superclass value where a subclass is expected because the subclass is more specific. So you can't return a Function1 value from a method typed to return a PartialFunction.

The inverse works though - you can use a subclass where a superclass is expected. So you can return a PartialFunction from a method typed to return a Function1 (with the same type parameters):

scala> def f: Any => Any = { case a => "foo" }
f: Any => Any

scala> f(1)
res0: Any = foo

In this particular case you can always convert a Function to a PartialFunction, so the PartialFunction.apply method is provided.

def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) }
sourcedelica
  • 23,940
  • 7
  • 66
  • 74
  • Thanks for the reply. I do have the concepts the correct way though, as I was referring to the fact a total function is a specialized case of a partial function (in general math not in Scala), so if you ask for a partial function, I should be able to give you a total function as that still fulfils the criteria. It was really just a kind of off the cuff, I wonder if, type of question, could I do ( any => any ) instead of case { any => any }. I really am turning into a Scala-zealot when I'm worried about saving a few characters :) – sksamuel Jan 06 '14 at 20:51
  • 1
    Gotcha - you're coming at it from the mathematics point of view. I thought you were thinking about the OO p.o.v. – sourcedelica Jan 06 '14 at 21:33
0

Time has moved on, Scala is at 2.13.5 and what is shown in the accepted answer is deprecated since Scala 2.12.5:

For converting an ordinary function f to a partial function pf, use val pf: PartialFunction[A, B] = { case x => f(x) }. For creating a new PartialFunction, use an explicit type annotation instead, like in val pf: PartialFunction[Int, String] = { case 1 => "one" }.

Also, consider the import scala.{PartialFunction => =/>} (in contrast to regular, total, functions =>). Since partial functions require writing out the type (aka adding type annotations) this saves you a lot of manual typing and improves readability, e.g.:

val yourPf: String =/> String = {
  case SomeRegEx(s) => s
}

Side note: On my machine PartialFunction.apply even results in the error PartialFunction.type does not take parameters.

phdoerfler
  • 470
  • 6
  • 19
-4

i think youre looking for the convenience method called "lift" which turns a partialfunction into a function1 (returning the result wrapped in an option).

http://www.scala-lang.org/api/current/index.html#scala.PartialFunction

speaking of the taxonomy; i think you got that backwards - a partialfunction is a subtype of function1

Stefan Kunze
  • 741
  • 6
  • 15