Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

splat rename 1.8 -> 1.9 #47714

Closed
aplavin opened this issue Nov 26, 2022 · 15 comments
Closed

splat rename 1.8 -> 1.9 #47714

aplavin opened this issue Nov 26, 2022 · 15 comments

Comments

@aplavin
Copy link
Contributor

aplavin commented Nov 26, 2022

In Julia 1.9:

help?> Base.Splat
  Splat(f)
<...>
  │ Julia 1.9
  │
  │  This function was introduced in Julia 1.9, replacing Base.splat(f).

Meanwhile, Base.splat remains, and seems equivalent to Base.Splat - but not documented. It's hard to see the rationale for changing the name to capital case.

The current situation is that Base.splat is available in both earlier julia versions and in 1.9, while Base.Splat only in 1.9. Given that, I find it hard to imagine someone using Base.Splat -- Base.splat has the same behavior and remains compatible with 1.8-.

Maybe, while 1.9 is not released yet, Base.splat should be documented as the official function splatting instead of Base.Splat?

@brenhinkeller
Copy link
Sponsor Contributor

Looks like that was introduced by #42717, not sure why capitalization was changed though

@brenhinkeller
Copy link
Sponsor Contributor

cc @Seelengrab

@Seelengrab
Copy link
Contributor

Seelengrab commented Nov 26, 2022

I'm a bit surprised that the change in capitalization (even without change in functionality!) is controversial :)

Base.splat has the same behavior and remains compatible with 1.8-.

That's not quite true - Splat has pretty printing to make it easier to know what function was wrapped in e.g. a stacktrace.
It's also still there in 1.9 thanks to the deprecation notice and retains its behavior until it's ultimately removed in a breaking release:

[sukera@tempman ~]$ julia -q --depwarn=yes
julia> versioninfo()
Julia Version 1.10.0-DEV.6
Commit 4cf077cd9a (2022-11-14 21:07 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: 4 × Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, skylake)
  Threads: 4 on 4 virtual cores
Environment:
  JULIA_NUM_THREADS = 4

julia> f() = Base.splat(+)
f (generic function with 1 method)

julia> f()
┌ Warning: `splat(x)` is deprecated, use `Splat(x)` instead.
│   caller = f() at REPL[1]:1
└ @ Main ./REPL[1]:1
Splat(+)

That's also the rationale for changing the capitalization, to signify that it's a bit more of a complicated object than just an anonymous function. Since its idiomatic to have struct names capitalized, this is too, similar to Fix1 and Fix2.

Though I'm open to not having the deprecation and just having it forward to Splat, if need be, I think it's beneficial consistency wise to call Splat(x) and then also get a Splat(x) back, instead of calling splat(x) and getting a Splat(x) back.

@aplavin
Copy link
Contributor Author

aplavin commented Nov 26, 2022

Base.splat has the same behavior and remains compatible with 1.8-.

That's not quite true - Splat has pretty printing to make it easier to know what function was wrapped in e.g. a stacktrace.

I mean that in 1.9 splat and Splat have the same behavior (Base.splat(f) === Base.Splat(f)), while only splat works in earlier versions.

That's also the rationale for changing the capitalization, to signify that it's a bit more of a complicated object than just an anonymous function. Since its idiomatic to have struct names capitalized, this is too, similar to Fix1 and Fix2.

Structs are capitalized, true. But this doesn't have anything to do with how they are created, what's the actual API. There's no shortage of examples where a struct (capitalized) isn't typically created with its constructor, but with a dedicated (lowercase) function. The function can either do some basic preprocessing of its arguments, or just pass them as-is to the constructor:

julia> zip([], [])
zip(Any[], Any[])
julia> zip([], []) |> typeof
Base.Iterators.Zip{Tuple{Vector{Any}, Vector{Any}}}

julia> Iterators.filter(identity, [])
Base.Iterators.Filter{typeof(identity), Vector{Any}}(identity, Any[])

Though I'm open to not having the deprecation and just having it forward to Splat, if need be, I think it's beneficial consistency wise to call Splat(x) and then also get a Splat(x) back, instead of calling splat(x) and getting a Splat(x) back.

I don't see any more consistency in calling Splat(f) than splat(f) - see examples above.
Meanwhile, there's consistency between julia versions: why would people use Splat and immediately make their code incompatible with 1.8-, when they can get the same behavior with splat and stay compatible?

@denius
Copy link

denius commented Nov 27, 2022

In any case, any version of Splat has never been exported from Base. Therefore, I suppose in the future, after a couple of versions of Julia, the new version of Splat will be renamed back to splat, and exported from Base.

@Seelengrab
Copy link
Contributor

Seelengrab commented Nov 27, 2022

while only Base.splat works in earlier versions.

That too can be solved with e.g. JuliaLang/Compat.jl#785, which should be used if you want new features on an older version once it is merged. That's pretty much how it has always worked.

There's no shortage of examples where a struct (capitalized) isn't typically created with its constructor, but with a dedicated (lowercase) function.

I'm aware of that, and I think it's a mistake that e.g. zip has that behavior, because it masks that this is a lazy object (even though it has been that way since its introduction in 2012, where the julia version was 0). Using lowercase zip means we can't have an eager version in the future with that name (which may be beneficial too), but adding such a thing cannot be done until a breaking release, which is unfortunate.

In any case, any version of Splat has never been exported from Base. Therefore, I suppose in the future, after a couple of versions of Julia, the new version of Splat will be renamed back to splat, and exported from Base.

I'm not sure I follow why adding a new thing implies renaming the new thing in the future. What exactly is the issue here, aside from aesthetic reasons?

@brenhinkeller
Copy link
Sponsor Contributor

Compat seems to have become a bit of an albatross from what I hear, so not sure if that is the perfect answer

That said, I don't think the name change is a big problem personally -- though I do still personally have a strong preference carried over from the pre 1.0 days for never breaking anything just for aesthetic reasons, so would probably personally lean towards keeping the lower-cased name for the splat function even if it returns the cool new upper case Splat object. In any case it's probably moot given that the lower case constructor can be relied on to keep working for all of 1.x at least

@Seelengrab
Copy link
Contributor

In any case it's probably moot given that the lower case constructor can be relied on to keep working for all of 1.x at least

Yes, exactly. Nothing breaks due to this, so from what I understand this is purely due to wanting to use the pretty printing on a version prior to 1.9 (understandable, since I'd have preferred to use it earlier too, else I wouldn't have made a PR for this UX in the first place!). If it's really desired, I guess we can discuss it on triage?

@aplavin
Copy link
Contributor Author

aplavin commented Nov 27, 2022

what I understand this is purely due to wanting to use the pretty printing on a version prior to 1.9

At least I didn't imply anything like this - no changes to older versions, they are fine as-is.

I'll try to explain my point again, there seems to be some confusion.
The current situation is:

  • Julia 1.9 introduces the Splat function. It creates a struct for some extra functionality/convenience, but otherwise equivalent to splat in older Julia versions.
  • Splat becomes the "official" interface, but splat remains - in 1.9 it's equivalent to Splat, in older versions uses a simplified implementation.

The question is, why not make splat the official interface? This function exists in all julia versions, can just be made documented/exported in 1.9.
That's everything I suggest.

I bet that most of the users (who need it) would continue using splat and not Splat anyway - due to its compatibility.

That too can be solved with e.g. JuliaLang/Compat.jl#785, which should be used if you want new features on an older version once it is merged.

Why add an extra dependency, when just using splat works on all Julia versions (unless new functionality is needed)?

I'm aware of that, and I think it's a mistake that e.g. zip has that behavior, because it masks that this is a lazy object <...> Using lowercase zip means we can't have an eager version in the future with that name

How does this have anything to do with lower/upper case? Current zip just should've been put to Iterators originally, exactly like map/Iterators.map, filter/Iterators.filter.

@aplavin
Copy link
Contributor Author

aplavin commented Nov 27, 2022

Anyway, this isn't a major issue, so I'll stop here. I just surely will continue using splat (not Splat) at least until 1.8 and earlier become totally irrelevant. Pretty sure most users would do the same instead of adding Compat.

@brenhinkeller
Copy link
Sponsor Contributor

Ok, I suppose we can close this, but if anyone wants to make a PR to adjust the docs or make the fallback permanent they can do that

@knuesel
Copy link
Member

knuesel commented Dec 28, 2022

@brenhinkeller, do you mean that I can make a PR to restore splat as non-deprecated API (and have Splat being simply the new way it's implemented internally)?

I would be happy to make such a PR if there's a chance to have it merged. It seems very natural to keep splat (now exported) and have it return a Splat. It's similar to many parts of the standard library, for example

  • used to return a lambda before 1.6 but now it returns an instance of ComposedFunction
  • The functions zip, filter, flatten, etc in Iterators return corresponding structs Zip, Filter, Flatten, ...
  • range(...) returns a struct such as UnitRange, StepRange, etc.

I agree with @aplavin: this rename is unnecessary and is just going to add confusion. We will forever have a mix of Base.splat and Splat in the wild and users will wonder what's the difference.

@brenhinkeller
Copy link
Sponsor Contributor

Sure!

@LilithHafner LilithHafner reopened this Dec 29, 2022
@LilithHafner LilithHafner added the status:triage This should be discussed on a triage call label Dec 29, 2022
@gbaraldi
Copy link
Member

gbaraldi commented Jan 5, 2023

Triage thinks we should keep the lower case splat as the interface users are expected to use and keep Splat unexported. If we think this is something users might want to use for dispatch we can always export it later.

@gbaraldi gbaraldi removed the status:triage This should be discussed on a triage call label Jan 5, 2023
@inkydragon
Copy link
Sponsor Member

Closed by #48038

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants