Issue 1:
I would like to propose allowing tuples of functions to be be callable and have the syntax:

(f,g)(x) = (f(x),g(x))

At the moment this is disallowed with an error, e.g.:

x = collect(1:10);
(minimum,maximum)(x)
julia> ERROR: MethodError:
objects of type Tuple{typeof(minimum),typeof(maximum)} are not callable
Stacktrace:
[1] top-level scope at REPL[7]:1

Another use for this would be to unpack the keys and values of a dictionary in a single line:

k,v = (keys, values)(mydict::Dict)

I do not know where callable is specified. Searching the docs for callable or in the help ?callable does not give anything concrete about how to allow something to be callable.

How should broadcasting work? I think a reasonable proposal is (f,g).(x) == (f.(x), g.(x)). Is this ambiguous or not desirable for a reason I cannot foresee?

Since f and g would be accessing the same input, and likely be doing similar operations, this introduces a performance issues. It makes it really easy to write non-performant code. My assumption was that there would be a lot of duplicated work if e.g. f and g both look through x separately, they should know to share common work.

This was motivated by the (minimum,maximum)(x) example. There is an existing function for this, extrema which should return the same result faster:

using BenchmarkTools

(T::Tuple{typeof(minimum),typeof(maximum)})(x) = (minimum(x),maximum(x))

x = rand(10^3);
@btime (minimum,maximum)($x)
@btime extrema($x)

On Julia-1.1:

julia> @btime (minimum,maximum)($x)
4.593 μs (0 allocations: 0 bytes)
(0.0010074908627801804, 0.9977385773243437)

julia> @btime extrema($x)
2.649 μs (0 allocations: 0 bytes)
(0.0010074908627801804, 0.9977385773243437)

So you can see that this callable tuple is twice as slow. EXCEPT!

On Julia-1.3:

julia> @btime (minimum,maximum)($x)
1.835 μs (0 allocations: 0 bytes)
(1.8361594563476302e-5, 0.9999551648541347)

julia> @btime extrema($x)
2.651 μs (0 allocations: 0 bytes)
(1.8361594563476302e-5, 0.9999551648541347)

Ummm. So now the tuple (minimum,maximum) is faster than extrema? I don't understand this. Some threading magic?

Anyway I think this is a general problem, is the compiler smart enough to let f and g know about the shared work between f and g and use them together?

I was going to propose explicitly dispatching to more efficient joint methods, e.g. (T::Tuple{typeof(minimum),typeof(maximum)})(x) = extrema(x) but not only is this ugly, very specific, and hopefully could be automatically made efficient by the compiler. It is also, as demonstrated above, less efficient than (minimum(x),maximum(x)) currently!

I don't know what to do in the case that f mutates x, or if we should do anything. If it is literally the case that (f,g)(x) = (f(x),g(x)) then I guess the order of these two matter. But if its possible to do these two functions in parallel, it might be a problem. I also don't know how that might affect shared work.

I would like to help implement this. I think it looks like setting up methods that look like

(T::Tuple{f::Callable,g::Callable})(x) = (f(x),g(x))

But as I said at the top, I don't know what decides if a type is callable.

Issue 2:
http://julia.readthedocs.org/en/latest/search/?q=ext&check_keywords=yes&area=default#