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 function argument for prod #19146

Closed
cossio opened this issue Oct 28, 2016 · 16 comments
Closed

Document function argument for prod #19146

cossio opened this issue Oct 28, 2016 · 16 comments
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request needs docs Documentation for this change is required

Comments

@cossio
Copy link
Contributor

cossio commented Oct 28, 2016

sum and mean both can take a function argument to apply to elements before summing or averaging, and this is documented:

?sum
sum(f, itr)

Sum the results of calling function f on each element of itr.

?mean
mean(f::Function, v)

Apply the function f to each element of v and take the mean.

But ?prod doesn't show the method that takes a function argument.

@tkelman tkelman added the help wanted Indicates that a maintainer wants help on an issue or pull request label Oct 28, 2016
@mbauman
Copy link
Member

mbauman commented Oct 28, 2016

Now that we have generators, maybe we could just deprecate those methods. sum(f(i) for i in itr) should be just as fast, and prod(f(i) for i in itr) works as is.

@johnmyleswhite
Copy link
Member

+1000 to removing these kinds of pre-composed generator + function patterns

@tkelman
Copy link
Contributor

tkelman commented Oct 28, 2016

function-first does allow do-block notation, is that doable with generators?

@cossio
Copy link
Contributor Author

cossio commented Oct 28, 2016

I find the generator syntax more readable than a do-block with function-first.

@andreasnoack
Copy link
Member

+1 for generators. In the rare occasions where your function definition is so big that a do block useful I think it would be okay to refer to mapreduce.

@ararslan
Copy link
Member

ararslan commented Oct 28, 2016

prod actually does take a function argument. On master (just a couple days old):

julia> methods(prod)
# 6 methods for generic function "prod":
prod(x::Tuple{}) at tuple.jl:222
prod(x::Tuple{Any,Vararg{Any,N<:Any}}) at tuple.jl:223
prod(f::Function, A::AbstractArray, region) at reducedim.jl:291
prod(f::Union{DataType,Function}, a) at reduce.jl:400
prod(A::AbstractArray, region) at reducedim.jl:293
prod(a) at reduce.jl:407

The third and fourth methods listed are the ones you want.

@cossio
Copy link
Contributor Author

cossio commented Oct 28, 2016

@ararslan The issue is that it's not documented.

@yuyichao yuyichao added the needs docs Documentation for this change is required label Oct 28, 2016
@johnmyleswhite johnmyleswhite changed the title prod doesn't take a function argument Document function argument for prod Oct 28, 2016
@johnmyleswhite
Copy link
Member

I changed the title to reflect that concern. Care to make a PR to fix this?

@StefanKarpinski
Copy link
Member

Deprecation in favor of generators seems like the better approach here.

@ararslan
Copy link
Member

Why can't both methods exist?

@StefanKarpinski
Copy link
Member

StefanKarpinski commented Oct 28, 2016

They can. I have to say that writing things like sum(length, arrays) is pretty nice. Nicer than sum(length(a) for a in arrays), so maybe just keep this and document it.

@StefanKarpinski
Copy link
Member

StefanKarpinski commented Nov 1, 2016

Ok, to flip sides again: the definition of reducer(transform, itr) methods for reducers is completely mechanical, which is exactly the sort of situation that we introduced f.(v) syntax to avoid – i.e. rather than call @vectorize_1arg and @vectorize_2arg on functions that support vectorization, let any function support vectorization. The only thing that's better about this situation is that unlike vectorization, there's a fairly clear answer to the question "which functions get these methods" – the answer is all reducers. While sum(length(a) for a in arrays) is pretty concise, I still can't think of a way to write this generically for any reducer that is as nice as sum(length, arrays). So maybe just define this method for all the built in reducers, which technically makes them map-reducers.

@cossio
Copy link
Contributor Author

cossio commented Nov 1, 2016

@StefanKarpinski What about sum(length.(arrays))? This is probably inefficient due to the intermediate array. Maybe one could have a notation like f:(v), which returns a generator instead of a full array like f.(v)? Or else f.(v) by default returns a generator, which must be explicitly converted to an array by a call to collect.

@StefanKarpinski
Copy link
Member

Yes, I considered that but it's inefficient since it materializes the array of lengths. The f:(v) notation isn't available since it already means the same thing a f:v – i.e. construct a range from f to v with unit step. Introducing laziness doesn't seem helpful here. I'm somewhat inclined to just define (and document) the map-reduce methods for all reducers since it is a fixed set of functions, at least in Base.

@cossio
Copy link
Contributor Author

cossio commented Nov 2, 2016

Sorry, : was a poor example (I forgot ranges). Maybe another punctuation is available for lazy map? I created a new issue to discuss this: #19198.

@Sacha0
Copy link
Member

Sacha0 commented Nov 2, 2016

Ref. discussion around #16285 (comment) (generalizing compact broadcast syntax to compact higher-order function syntax, relevant given the behavior mentioned above is mapreduce). Best!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request needs docs Documentation for this change is required
Projects
None yet
Development

No branches or pull requests

9 participants