`flip` and deprecation

flip was removed in 0.19. I’d like to note that such changes are worse for book authors than for app authors. And ask that, in the future, such changes be made less suddenly.


My An Outsider’s Guide to Statically Typed Functional Programming uses flip in chapter 1 (“Functions”). flip is a really excellent example: it clarifies partial application and related topics. I’ve gotten good feedback about that chapter.

Last week, I gave a talk at NewCrafts Bordeaux on “My Best Advice (Today) About Adopting Functional Programming”. I gave everyone coupons for free copies of the book, which was written against 0.18.

Some people both downloaded the book and started working through the exercises. So now I get emails about how the first chapter’s examples don’t work.

This places neither Elm, nor me, in a good light.

Maybe flip is unnecessary in a minimal language - I really can’t argue with that - but it’s not so harmful that it must be abruptly removed. A deprecation notice would have been a big help to me.

6 Likes

@marick it sounds like you’re asking for better deprecation in general? Did you have a particular mechanism in mind? Here’s a few I thought of but all of them have drawbacks :disappointed:

Compiler deprecations

Perhaps having the compiler special-case the “no function found with this name” error for function names that were removed from elm-lang/core in the previous version? Although maybe that would couple the compiler and elm/core library too much. :thinking: It also only works for core packages.

Stubbed implementations

If we wanted to do this without the compiler, maybe the 0.19 compatible elm/core library could do something like:

flip : (a -> b -> c) -> b -> a -> c
flip func a b =
  Debug.todo "This function was deprecated"

Although I guess Debug.todo is not allowed in packages. I suppose you could whitelist elm/core to allow this but then you’ve broken some guarantees. Also this only works for core packages.

Command-line tool

CLI tools like elm-upgrade can warn you of deprecated functions. Most app developers probably use this when going from 0.18 → 0.19 but readers of a book probably would not.

Disclaimers

Outside of the language, I suppose you could have a big disclaimer in the book along the lines of

This code is written for Elm 0.18. If you’re using a later version of the language check the relevant changelog and run necessary upgrade tools on the code

I often do some variation of this in blog posts so people who find them via Google a few years down the road know what they’re getting into.

Of course, some readers will ignore it and still email you asking why the code is wrong :grimacing:

1 Like

I think it would be great to be able to add a @deprecated keyword into the doc comment for a function so that the function will still work, but it will be highlighted as deprecated on the package website and produce a compiler warning if used (once compiler warnings come back).

I generally use a process like:

  • Deprecate a function in a minor release (typically when adding its replacement)
  • Add a big bold DEPRECATED note in that function’s documentation
  • Remove the function in the next major release (with a comment in the release notes mentioning its replacement)

This works, and in theory it gives people time to upgrade before their code breaks, but only if they happen to read the documentation for the minor release and see that the function they’re using has been deprecated. If instead their code started giving them warnings, it would be much harder to miss!

2 Likes

I think the sudden deprecation is what bothers people. Also it is fine for 0.x releases and makes stuff a lot less complicated.

On the future we could have a longer phase where the old behavior is supported but triggers a warning.

I once heard story of a system.library slowing a deprecated function down exponentially, to make it less usable with every release.

Why not mix those and provide a language primitive specifically for deprecation, that breaks on compilation ?

flip : (a -> b -> c) -> b -> a -> c
flip func a b =
  deprecated

If the language keeps moving fast and breaking things, it may as well get the tooling to do so with minimum harm.

1 Like

Joël, I think you’re talking about dealing with a function that is gone rather than deprecated. Deprecation means the function is still available in version N (but produces a deprecation warning) and gone in version N+1. Deprecation should also be announced in the release notes and highlighted in the docs. If an automatic upgrade is possible, then elm-upgrade would perform it. It seems to me to be a solved problem conceptually.

However, like many other things, the feasibility of having a deprecation process comes down to timelines and resources. flip happens to be a trivial case, but in an extreme case, you’d need to include the whole previous version of the compiler and standard library to maintain the deprecated functionality.

I happen to have the same issue in my book as I talk about flip briefly, although I haven’t had complaints as I’ve been communicating with the readers about the state of the book and updates to 0.19. For now, I make it clear that the book is still based on Elm 0.18. FWIW, I’m just going to provide the implementation of flip, and still talk about it.

Ideally, a deprecation process is helpful, but as I said in my response to Joël, it’s a matter of resources and priorities, and I suspect that a general purpose deprecation process is a serious implementation effort (and significant added complexity).

I agree with this wholeheartedly. At work we have something like 50,000 lines of Elm code across 8 different applications. As much as I want to push to upgrade to 0.19, it’s the sum of all of the changes that make this a big task for my small team. I would have appreciated deprecation notices for core library changes as well as non-fundamental syntax changes (like the new 3-value limit on tuples).

I realize that library deprecation notices and syntax deprecation notices likely require a vastly different implementation, but both would help. Having between now and the next Elm release to remove things like flip and 4-value tuples in our code would make the upgrade process more incremental and likely allow us to do the initial switch to 0.19 sooner.

Can I add my “I agree” here too?

In addition to book writing / publishing, which has a much less agile production cycle than individual app development, teaching students using Elm isn’t ideal when unexpected changes to the language occur.

Typically, as a teacher I might have to prepare my materials months in advance of delivery and the delivery itself can occur over a semester (14 weeks). If examples that students might have been given suddenly don’t work, it can be disruptive to learning, even if the solution to any one problem is straight forward.

Maybe a formal deprecation system might be too much to ask at this stage, but perhaps some obvious location where at least the direction of future changes might be signalled. This would allow us to steer away from potentially problematic idioms (e.g. 4-tuples) in advance of language changes. I seem to recall there was something in the API docs that did indeed signal that large tuples were discouraged, so this kind of worked. But removal of toString, scanl, flip, (,) and % took me by surprise (even though the changes might be desirable ones).

This approach also has the benefit of steering good practice (and revealing unintended consequences) in advance of being forced to do so by the language itself.

3 Likes

Might this issue be helped by having an unstable or development branch of the compiler publicly available so people can see the roots of things coming down the pipe?

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.