Scala: return function selection Option compared to PartialFunction

I am a relative Scala newbie and would like some advice on how to proceed with an implementation that seems to be able to be executed with either a function returning Option or a PartialFunction. I read all the related entries I could find (see the bottom of the question), but they seem to be related to the technical details of using PartialFunction or converting one to another; I am looking for an answer like "if the circumstances are X, Y, Z, and then use A else B, but also consider C".

My use case is finding paths between locations using a path search library. Suppose the locations are of type L , the path is of type P , and the desired path search result is Iterable[P] . The result of the patch search should be compiled by requesting all search devices (for example, Google maps, it can be bicycles, car, walk, metro, etc.) For their suggestions along the way, which may or may not be determined for a particular launch end point.

There seem to be two ways to do this:

(a) define the path search as f: (L,L) => Option[P] , and then get the result through something like finders.map( _.apply(l1,l2) ).filter( _.isDefined ).map( _.get )

(b) define the path search as f: PartialFunction[(L,L),P] and then get the result via something like finders.filter (_. isDefined ((l1, l2))). map (_. apply (( l1, l2))) `

It seems that using the function returning Option[P] will avoid double-evaluating the results, so for an expensive calculation, this might be preferable if not caching the results. It seems that using Option may have an arbitrary input signature, while PartialFunction expects a single argument. But I am particularly interested in hearing from someone with practical experience regarding less direct, more β€œwider” considerations, such as interacting with the Scala library. Will using PartialFunction have significant advantages in providing certain collection API methods that can pay off in other ways? Would such code be more concise?

Related but different questions:

+6
source share
2 answers

Option seems to be better suited to your use case.

My interpretation is that partial functions work well for combining input ranges. Therefore, if f defined over (SanDiego,Irvine) and g defined (Paris,London) , then you can get the function defined over the combined input (SanDiego,Irvine) and (Paris,London) by doing f orElse g .

But in your case, everything seems to happen for the given tuple (l1,l2) , and then you do some work ...

If you find that you write a lot {case (L,M) => ... case (P,Q) => ...} , then this may be a sign that partial functions are better suited.

Otherwise, the parameters will work well with the rest of the collections and can be used like this instead of your (a) sentence:

 val processedPaths = for { f <- finders p <- f(l1, l2) } yield process(p) 

Inside the understanding, p goes up to Traversable , so you don’t even have to call filter , isDefined or get to skip the crawlers without results.

+3
source

This is not all that is well known, but since 2.8 Scala has a collect method defined on it by collections. collect is similar to filter , but accepts a partial function and has the semantics that you describe.

+3
source

Source: https://habr.com/ru/post/902813/


All Articles