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

Document map, separate map and collect #39628

Open
goretkin opened this issue Feb 11, 2021 · 0 comments
Open

Document map, separate map and collect #39628

goretkin opened this issue Feb 11, 2021 · 0 comments
Labels
docs This change adds or pertains to documentation

Comments

@goretkin
Copy link
Contributor

goretkin commented Feb 11, 2021

This might be better as two separate issues, since on one hand I want to document what map is now, and on the other hand I want behavior for map that might need to wait until a breaking release. But I don't know where the boundary between those two are.

Regarding documentation, there is currently one docstring defined for map:

julia/base/abstractarray.jl

Lines 2305 to 2328 in 4f854b4

"""
map(f, c...) -> collection
Transform collection `c` by applying `f` to each element. For multiple collection arguments,
apply `f` elementwise.
See also: [`mapslices`](@ref)
# Examples
```jldoctest
julia> map(x -> x * 2, [1, 2, 3])
3-element Vector{Int64}:
2
4
6
julia> map(+, [1, 2, 3], [10, 20, 30])
3-element Vector{Int64}:
11
22
33
```
"""
map(f, A) = collect(Generator(f,A))

This docstring does not capture the behavior of map on e.g. NamedTuple. It does not describe what is done with the result of applying f to each element. (As an aside, it is worth clarifying that the meaning of "each element" is defined by the iterate interface.)

Where possible, I think we should document behavior in terms of properties such as

map(identity, c) == c

See #38150 (comment) . As that thread indicates, that property doesn't currently hold, because map is conflated with collect. To relate the behavior of map and collect, I expect the following property

map(f, collect(c)) == collect(map(f, c))

One example where the property doesn't hold is with Generators:

julia> c = (x for x in 1:4)
Base.Generator{UnitRange{Int64},typeof(identity)}(identity, 1:4)

julia> map(identity, c)
4-element Array{Int64,1}:
 1
 2
 3
 4

That property could hold with the following definitions:

Base.:(::(typeof(identity)), f) = f
Base.map(f, g::Base.Generator) = Base.Generator(f  g.f, g.iter)

This will break code that was using map for its collect behavior. Some examples (with some false positives from splatting arguments from a generator into map) can be found with the regex map\([^,]*,\s*\(.*for.*in .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs This change adds or pertains to documentation
Projects
None yet
Development

No branches or pull requests

2 participants