nargout can be emulated by (ab)using the iteration protocol on a custom return type that will be accessed through tuple assignment/destructuring.
Take this example: tpl = (1,2) a,b = tpl the second line will call start(), done() and next() on tpl to extract the two numbers. So, for your use case: type Result; output1; otherstate; end function myfunc(x, y) return Result(x+y, (x, y)) end my_expensive_func(r::Result) #compute output2 end start(r::Result) = 1 done(::Result, i) = i > 2 function next(r::Result, i) if i == 1 (r.output1, 2) elseif i == 2 (my_expensive_func(r), 3) end end to get the first result, use this (note the coma): a, = myfunc(4,5) Hopefully this helps :-) —Pierre-Yves On Fri, Mar 6, 2015 at 8:47 PM, Tim Holy <tim.h...@gmail.com> wrote: > 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 >