Is there an idiomatic way to discard values returned from a function

405 views
Skip to first unread message

Gray Calhoun

unread,
Oct 15, 2014, 11:23:20 AM10/15/14
to julia...@googlegroups.com
Hi everyone, if a function returns multiple values, is there an idiomatic way to discard all but (say) the 3rd value returned? For example:

f(x, y, z) = return x^2, y^3, z^4
_
, _, v = f(1, 2, 3)

expresses the intent to only use the third value returned, but surely is inefficient.

Thanks!

Jiahao Chen

unread,
Oct 15, 2014, 11:24:59 AM10/15/14
to julia...@googlegroups.com
You can do

v = f(1, 2, 3)[3]

Thanks,

Jiahao Chen
Staff Research Scientist
MIT Computer Science and Artificial Intelligence Laboratory

Gray Calhoun

unread,
Oct 15, 2014, 11:33:21 AM10/15/14
to julia...@googlegroups.com
Oh, that's embarrassingly obvious in retrospect. Thanks!

Duane Johnson

unread,
Oct 15, 2014, 12:37:37 PM10/15/14
to julia...@googlegroups.com
I'm embarrassed I didn't think of it either. Just letting you know the embarrassment is distributed and not all on your shoulders :)

Ethan Anderes

unread,
Oct 15, 2014, 2:54:39 PM10/15/14
to julia...@googlegroups.com

However, this doesn’t work if you want to pick out more than one variable. E.g.

julia> function foo() 
        1,2,3 
       end 
foo (generic function with 1 method) 

julia> _, x, y = foo() 
(1,2,3) 

julia> x 
2 

julia> y 
3 

julia> _, x, y = foo()[2:3] 
ERROR: BoundsError() 
 in indexed_next at /Users/ethananderes/Software/julia/usr/lib/julia/sys.dylib (repeats 2 times)

Is there a fancy way to handle this case?

Cheers,

Ethan

Ethan Anderes

unread,
Oct 15, 2014, 2:57:46 PM10/15/14
to julia...@googlegroups.com

Oops, now I’m embarrassed. This is obviously how you do it.


julia> x, y = foo()[2:3]
(2,3)

julia> x
2

Patrick O'Leary

unread,
Oct 15, 2014, 3:12:15 PM10/15/14
to julia...@googlegroups.com
You still have the "_" in there.

x,y = foo()[2:3] should work fine.

Christoph Ortner

unread,
Oct 16, 2014, 7:15:03 PM10/16/14
to julia...@googlegroups.com
x,y = foo()[2:3]

is clearly a possible way to do it, however, the MATLAB syntax

~, x, y = foo()

is **much** easier to read. Would it be worthwhile to request introducing something like this?

Christoph

Andreas Noack

unread,
Oct 16, 2014, 7:19:06 PM10/16/14
to julia...@googlegroups.com
You can already do that in Julia
In [70]:
_,_,x = f(1,2,3);x
Out[70]:
81

Med venlig hilsen

Andreas Noack

Simon Kornblith

unread,
Oct 16, 2014, 8:01:41 PM10/16/14
to julia...@googlegroups.com
It's not really very inefficient. Compare:

julia> f(x, y, z) = return x^2, y^3, z^4;

julia
> g(a, b, c) = f(a, b, c)[3];

julia
> @code_llvm g(1.0, 1.0, 1.0)

define
double @"julia_g;767954"(double, double, double) {
top
:
 
%3 = call double @pow(double %2, double 4.000000e+00), !dbg !525
  ret
double %3, !dbg !525
}

julia
> function g(a, b, c)
           _
, _, v = f(a, b, c)
           v
       
end;

julia
> @code_llvm g(1.0, 1.0, 1.0)

define
double @"julia_g;767955"(double, double, double) {
top
:
 
%3 = call double @pow(double %2, double 4.000000e+00), !dbg !528
  ret
double %3, !dbg !530
}

If the return values are bits types, the optimizer is smart enough that there's no overhead to pulling unused variables out of tuples. (In this case, f was inlined, so g doesn't even compute x^2 or y^3.) At present,  _, a, b = f(x, y, z) will actually be more efficient than a, b = f(x, y, z)[2:3], since the latter will allocate a new tuple on the heap, although that could probably be improved.

If the return values are not bits types, or if the return type of f is not inferrable, there will be slight overhead to pulling an unused value out of a tuple, but in the former case the time to allocate the unused return values will be vastly greater, and in the latter case the type instability would be a performance bottleneck no matter what.

Simon
Reply all
Reply to author
Forward
0 new messages