Skip to content

Conversation

@Jasper-M
Copy link
Contributor

@Jasper-M Jasper-M commented Jul 25, 2017

Follow up of #5897.

Unfortunately apply can't be overloaded...
I suggest replacing this apply with one that accepts a PartialFunction as soon as possible. In my opinion

val pf = PartialFunction[Int, String] { case 1 => "one" }

looks and feels better than

val pf: PartialFunction[Int, String] = { case 1 => "one" }

I am open to suggestions for improving the deprecation message. It doesn't cover the fact that for instance def foo(pf: PartialFunction[Int, String]) = ???; foo{ case 1 => "one" } just works without explicit types at the use site. But I fail to put that in a short, understandable message that doesn't throw terms like "expected type" in an unsuspecting user's face. I might be overthinking this.

@scala-jenkins scala-jenkins added this to the 2.13.0-M3 milestone Jul 25, 2017
@lrytz
Copy link
Member

lrytz commented Jul 26, 2017

Maybe we can deprecate PF.apply in 2.12.4 and remove it in 2.13? Then we could bring it back (with a PF parameter type) in 2.14.

@Jasper-M
Copy link
Contributor Author

I didn't know you could deprecate something in the middle of a release cycle.

@lrytz
Copy link
Member

lrytz commented Jul 26, 2017

I think usually not, but this might be exotic and confusing enough to make an exception.

@Jasper-M
Copy link
Contributor Author

Why can't you remove it and replace it in one go?

@hrhino
Copy link
Contributor

hrhino commented Jul 26, 2017

@Jasper-M I think that it's that if you repeal remove and replace it on one go, then code like

val x = PartialFunction[String, Boolean] { case "bippoid" => true }

will compile before and after, but have silently different semantics, which is potentially a pitfall for migration. Granted, the 2.12.x behaviour is almost certainly not wanted, but still...

@Jasper-M
Copy link
Contributor Author

True, but is that still the case when you deprecate something in the beginning a new major release (2.13.0 for instance)? Cause then it's been deprecated for a whole release cycle. Then you can't say you haven't been warned.

@adriaanm
Copy link
Contributor

Let's deprecate apply in 2.12.5 and drop it in 2.13. Maybe we shouldn't be using apply at all here, because it's just confusing in general when dealing in functions? Adding a type ascription as suggested by the deprecation message is cleaner anyway, IMO.

@SethTisue
Copy link
Member

👍 to that plan — as I understand it, the recommended upgrade path for users to move to a new major Scala release has always been to upgrade to the newest point release from the last version first, fix all deprecation warnings, then bump the major version

@Jasper-M
Copy link
Contributor Author

Sounds good. I'll clean this up somewhere this week.

@Jasper-M Jasper-M changed the base branch from 2.13.x to 2.12.x November 30, 2017 09:49
@Jasper-M Jasper-M changed the base branch from 2.12.x to 2.13.x November 30, 2017 09:50
@Jasper-M Jasper-M force-pushed the topic/partial-functions branch from 5fcaa15 to 6562ee4 Compare November 30, 2017 11:07
@Jasper-M Jasper-M changed the base branch from 2.13.x to 2.12.x November 30, 2017 11:08
@Jasper-M
Copy link
Contributor Author

Jasper-M commented Nov 30, 2017

If we deprecate apply in 2.12.5, we can't add fromFunction at the same time. Should the deprecation message suggest using val pf: PartialFunction[A,B] = { case x => f(x) } instead of PartialFunction(f)? And then add fromFunction in a separate pull request to 2.13.x?

A hypothetical workaround might be to implement fromFunction in 2.12.5 with a macro...

@adriaanm
Copy link
Contributor

adriaanm commented Nov 30, 2017 via email

@Jasper-M
Copy link
Contributor Author

I don’t see why we can’t add fromFunction in 2.13 immediately. The deprecation message can’t refer to it in 2.12, true.

Well yes, then I would need separate pull requests for both?

Then again, do we need it at all? I don’t know, having a hard time imagining the use case

I'm not sure, but it's there so I guess people might be using it. The best use case I can imagine is circumventing some badly designed API.

@adriaanm
Copy link
Contributor

adriaanm commented Nov 30, 2017 via email

@Jasper-M
Copy link
Contributor Author

Fine by me. I don't use it anyway 😅

@Jasper-M Jasper-M force-pushed the topic/partial-functions branch from 6562ee4 to 0cddad7 Compare December 1, 2017 09:32
PartialFunction.apply causes confusion because at first glance it looks
like a general purpose factory method for creating PartialFunctions, but
it is only meant to convert ordinary to partial functions (with
`pf.isDefinedAt(x) == true` for all x). When used in the wrong way it
can have confusing semantics.
@Jasper-M Jasper-M changed the title Deprecate PartialFunction.apply and add PartialFunction.fromFunction Deprecate PartialFunction.apply Dec 1, 2017
@adriaanm adriaanm modified the milestones: 2.13.0-M3, 2.12.5 Dec 13, 2017
@adriaanm adriaanm merged commit 17d7a7d into scala:2.12.x Dec 13, 2017
@SethTisue SethTisue added the release-notes worth highlighting in next release notes label Dec 13, 2017
@nafg
Copy link
Contributor

nafg commented Feb 25, 2018

FWIW I'm pretty sure I've had times where I had a function instance and something expected a PartialFunction, and .apply came in handy.

@adriaanm
Copy link
Contributor

Definitely, but this is about the apply method in the companion -- sounds like you're talking about the one in the class?

@nafg
Copy link
Contributor

nafg commented Feb 26, 2018

No, on the companion. (I suppose the instance method would be the opposite case but anyway that's definitely not what I'm talking about!)

@SethTisue
Copy link
Member

I'm not sure we reached a clear conclusion on whether there ought to be a followup PR that adds PartialFunction.fromFunction in 2.13. "I'm pretty sure I've had times" suggests that perhaps we should, but I think we probably need clearer evidence than that in order to justify it.

related but separate question — do we want to actually remove PartialFunction.apply in 2.13, or just leave it deprecated one version longer? we do like to get rid of deprecated stuff, but to actually get rid of it in 2.13 when the deprecation hasn't even happened yet (2.12.5 isn't out yet) seems like an especially fast timetable for removal to me, I don't think we need to get rid of stuff quite that fast unless it's standing in the way of something else.

@Jasper-M
Copy link
Contributor Author

Jasper-M commented Feb 26, 2018

Perhaps add fromFunction and adjust the deprecation message in 2.13 then?

@ShaneDelmore
Copy link
Contributor

If it helps, I am absolutely sure I have needed PartialFunction.fromFunction quite a bit. I am not sure if it's an edge case but I work with scalafix a fair bit which has an api that is largely based around collecting over trees, and it isn't that uncommon to find myself down a path where at a particular point I have a partial function and it wants a partial function.

@nafg
Copy link
Contributor

nafg commented Feb 27, 2018 via email

@lrytz lrytz added 2.12 and removed 2.12 labels Mar 14, 2018
@sarahgerweck
Copy link

I just want to chime in with my 2¢ that I don't like the proposal (perhaps no longer on the table) to replace this with a new apply in 2.13.0. It seems unnecessarily dangerous to deprecate something in 2.12.5 and then replace it with a method that will accept the old source code but silently misbehave in 2.13.0.

If the plan is ultimately to replace the apply with a source-incompatible version, my (unsolicited) opinion would favor removing it in 2.13 rather than leaving it with a deprecation. Yes, there would have been a deprecation for a full version cycle, but the consequences of the behavior change if somebody misses the deprecation warning are potentially catastrophic. (It is clearly a good idea to enable them, but scalac doesn't even show the actual deprecation warnings by default.)

The need to cross-compile libraries in Scala exacerbates the issue as people have code that's simultaneously compiled against several versions. A compilation failure makes clear the danger here.

I'm also +1 for adding a PartialFunction.fromFunction (or Function.toPartial). When basic stuff like this is left out of the standard library, it just winds up accumulating little helpers in a million projects. I think there are enough use cases that it belongs

@nafg
Copy link
Contributor

nafg commented Mar 21, 2018 via email

@adriaanm
Copy link
Contributor

Thanks, @sarahgerweck, and your opinion is very much solicited, and appreciated. I share the concern of silently changing behavior. We can't assume all deprecation warnings will be seen.

So, to summarize proposed next steps: add fromFunction in 2.13 and drop apply. Once available, we can update the deprecation message in 2.12.x to say this will be available as fromFunction in 2.13. It should be easy to cross-compile using fromFunction in both versions, supplying it as an extension method on 2.12. I do think the distance between 2.12 and 2.14 is great enough that we could consider adding apply again as a shorter version for fromFunction, although I'm not that worried about terseness, and more about clarity. apply is too overloaded in this context.

@nafg, sorry for misunderstanding your earlier comment. Do you find this an acceptable compromise?

PS: If we are too worried about dropping apply (I'm not), we could instead add an implicit argument of type DoNotUse, with an implicitNotFound annotation that says to use fromFunction :-) This makes it very unlikely people will call it accidentally, and provides another helpful migration message.

@Jasper-M
Copy link
Contributor Author

Jasper-M commented Mar 21, 2018

So, to summarize proposed next steps: add fromFunction in 2.13 and drop apply. Once available, we can update the deprecation message in 2.12.x to say this will be available as fromFunction in 2.13.

Sounds good to me.

It should be easy to cross-compile using fromFunction in both versions, supplying it as an extension method on 2.12.

You mean the person who is cross-compiling can easily add that extension himself?

I do think the distance between 2.12 and 2.14 is great enough that we could consider adding apply again as a shorter version for fromFunction, although I'm not that worried about terseness, and more about clarity. apply is too overloaded in this context.

The short version of fromFunction is what was deprecated here 😜 But I agree it's probably better not to add a different apply after removing this one.

@lrytz
Copy link
Member

lrytz commented Mar 21, 2018

Nit, but it seems to me PartialFunction.from is enough, PartialFunction.fromFunction is redundant.

@nafg
Copy link
Contributor

nafg commented Mar 21, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes worth highlighting in next release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants