I'll take it in the opposite direction of uniformity, and point out that 
another useful approach is to pass the optional output in as an argument:

function myfunction!(output2, input1, input2, ...)
    # do some calculations
    if !isa(output2, Nothing)
        for i = 1:n
            output2[i] = ...
        end
    end
    output1
end

output1 = myfunction!(nothing, x, params)
g = Array(T, sz)
output1 = myfunction!(g, x, params)

This is used extensively in optimization, where output2 might be storage for 
the gradient.

Best,
--Tim


On Friday, March 06, 2015 08:24:08 PM Milan Bouchet-Valat wrote:
> Le jeudi 05 mars 2015 à 11:59 -0800, Pooya a écrit :
> > Thanks for this clear explanation. If I do the following, is my
> > function type still unstable? How do you compare the following
> > solution to yours in terms of efficiency, style, etc?
> > 
> > function compute_outputs(..., output2Flag)
> > 
> >   # do some stuff, get x, y, and z
> >   # compute output 1
> >   output1 = ...
> >   if output2Flag
> >   
> >     # compute output 2
> >     output2 = ...
> >   
> >   else
> >   
> >     output2 = SparseMatrixCSC[]  # the same type as output2 when it is
> > 
> > computed
> > 
> >   end
> >   return output1, output2
> > 
> > end
> 
> This version indeed appears to be type-stable, so it should be quite
> efficient. Users will also be able to write
> a, b = compute_outputs(..., false)
> or
> a, = compute_outputs(..., false)
> when they don't care about the second output. So it's not a bad design,
> but returning a second output even when not needed isn't super
> satisfying.
> 
> Thus, maybe Steven's suggestion to create two separate functions is
> better. Do you have any reason to think it's not practical for your
> case?
> 
> We should probably decide what's the most idiomatic solution, and
> document it to ensure consistency. What do other people think?
> 
> 
> Regards
> 
> > On Thursday, March 5, 2015 at 10:58:02 AM UTC-5, Steven G. Johnson
> > 
> > wrote:
> >         On Wednesday, March 4, 2015 at 6:38:28 PM UTC-5, Pooya wrote:
> >                 Thanks for your response. I am not sure what you mean
> >                 by a lower-level subroutine. Is that a function inside
> >                 another one? If yes, How does the scope of variables
> >                 work for that?
> >         
> >         From your description, right now you have:
> >         
> >         
> >         function compute_two_outputs(...)
> >         
> >                ...do some stuff, get x, y, and z....
> >                ....use x, y, and z to compute output1....
> >                ....use output1, x, y, and z to compute output2....
> >               
> >               return output1, output2
> >         
> >         end
> >         
> >         
> >         Instead, if you don't always want to compute both outputs, but
> >         still want to write the shared computations only once, you can
> >         refactor the code to pull out the shared computations into
> >         another function (that is "lower level" in the sense that
> >         users won't normally call it directly):
> >         
> >         
> >         function some_stuff(...)
> >         
> >                ...do some stuff, get x, y, and z....
> >                ....use x, y, and z to compute output1....
> >                return output1,x,y,z
> >         
> >         end
> >         
> >         
> >         function compute_output1(...)
> >         
> >               return some_stuff(...)[1]
> >         
> >         end
> >         
> >         
> >         function compute_two_outputs(...)
> >         
> >                output1,x,y,z = some_stuff(...)
> >                ....use output1, x, y, and z to compute output2....
> >               
> >               return output1, output2
> >         
> >         end

Reply via email to