Thanks for this interesting solution! Coming from MATLAB, where data is passed by value, this did not make much sense to me, however, when passing inputs to functions by reference, this works very well. Interesting that you mentioned about the case in optimization, as this is in fact what I'm doing. This function computes some mismatch function (a vector g(x)), the second output is the Jacobian of that (dg/dx), and the objective is to minimize 1/2 * g(x)' * g(x). By the way, the jacobian is computationally expensive either in MATLAB or Julia.
On Friday, March 6, 2015 at 2:47:21 PM UTC-5, Tim Holy 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 > >
