4

Some reference code uses the function deal() trivially, like

[a, b, c] = deal (1,2,3)

As described in the documentation (for Octave and for MATLAB), the function simply copies the inputs to the outputs. Why use deal() in this case, or even in general? I'm trying to learn "more correct" MATLAB/Octave usage, and wondering if I'm missing something significant. Perhaps, is this usage...

  • conventionally stylistic or idiomatic, in place of simple assignment like a=1, b=2, c=3 or the more arcane list-unpacking of cell-arrays like [a,b,c] = {1,2,3}{:}, but even more restricted than Python argument unpacking, like in this question?
  • useful for some more elegant feature -- e.g., "deep" versus "shallow" copy, if such a concept even exists here, if deal() were used with complicated/variable arguments?

I also understand single-argument [a,b,c]=deal(42) but that's essentially a=b=c=42, and [a,b,c]=deal(x) assigns x to all, not elements-of-x to each.

Or perhaps it's ONLY that I'm over-thinking this trivial use of the function.

Community
  • 1
  • 1
hoc_age
  • 1,945
  • 2
  • 18
  • 28
  • 1
    It is a totally trivial function, type in `edit deal` and take a look at the code. You do not need deal, I never used it and never missed it. – Daniel Jun 13 '14 at 16:21
  • 1
    I guess you answered your own question. As far as I know, there is no other reason to use `deal()` other than readability. The "deep" vs. "shallow" copy question that you raised is irrelevant here (at least in Octave), because the interpreter is smart enough to detect when `a = b` needs to actually be copied in memory. – juliohm Jun 13 '14 at 16:48
  • Is there an analogous function in C? – Bryson S. Feb 01 '16 at 02:45
  • @BrysonS. -- There is no analogous function in C for a few reasons. The MATLAB `deal` function takes a variety of inputs (scalar, comma-separated list, cell-array, structure-array accessor, ...), so you'd have to do something like [tagged unions](http://stackoverflow.com/a/479266/3562032). Or you could use some wacky variadic stuff or C++. Multiple output values is a problem, so you'd have to return arrays or structs or pointers, ... but this seems far too complicated. What's the application? – hoc_age Feb 02 '16 at 02:34

2 Answers2

6

One really useful way that I occasionally use deal is to create anonymous functions that return multiple output arguments. For example,

>> f = @(x) deal(x^2,x^3);
>> [a,b] = f(3)
a =
     9
b =
    27

Edit since people seem to find this pattern potentially useful, do note a quirk, in that you must return the full number of outputs. In particular, you can't use a = f(3), or it will error. To retrieve just a single output, use [a,~] = f(3) or [~,b] = f(3). The ~ syntax for suppressing output arguments has been around since about R2007a or so (I'm afraid I can't recall exactly when) - in older versions, you will need to always return both outputs. Hope that may be useful for you.

Sam Roberts
  • 23,951
  • 1
  • 40
  • 64
  • 1
    Clever indeed, and I don't immediately see any other way of doing that; playing around with a few indexing and cs-list don't seem to work right. That should go on the docs for [anonymous functions](http://www.gnu.org/software/octave/doc/interpreter/Anonymous-Functions.html) or for `deal`! – hoc_age Jun 13 '14 at 20:32
  • Is there something like this in C? – Bryson S. Feb 01 '16 at 02:45
  • @BrysonS. -- see my response to your similar comment under the question itself. – hoc_age Feb 02 '16 at 02:35
3

First, your named examples work with octave, but not with matlab!

octave:1> a=b=c=42
a =                   42
octave:2> [a,b,c] = {1,2,3}{:}
a =                    1
b =                    2
c =                    3


>> a=b=c=42
 a=b=c=42
    |
Error: The expression to the left of the equals sign is not a valid target for an assignment.

>> [a,b,c] = {1,2,3}{:}
 [a,b,c] = {1,2,3}{:}
                  |
Error: Unbalanced or unexpected parenthesis or bracket.

How and when to use deal() can not be generalized. It depends on you scripte, your datastructure, what you want to do and how the result should look like etc.

>> m=rand(3,3);
>> [a,b,c]=m;
Too many output arguments.

>> [a,b,c]=reshape(m,[],1);
Error using reshape
Too many output arguments.

>> [a,b,c]=deal(reshape(m,[],1));
>> 

So some functions are designed with nargout = 1 and you can easily distribute the output to sevaral variables in "one line".

And if a functions has more nargouts than 1, it gets interesting

>> [x,y,z]=qr(m)

x =

   -0.7004    0.6471   -0.3012
   -0.1144   -0.5183   -0.8475
   -0.7045   -0.5592    0.4370


y =

   -1.3776   -0.7928   -1.2897
         0   -0.6388   -0.0796
         0         0   -0.3499


z =

     1     0     0
     0     0     1
     0     1     0

>> [x,y,z]=deal(qr(m))

x =

   -1.3776   -1.2897   -0.7928
    0.0673   -0.3588   -0.1418
    0.4143   -0.1886    0.6229


y =

   -1.3776   -1.2897   -0.7928
    0.0673   -0.3588   -0.1418
    0.4143   -0.1886    0.6229


z =

   -1.3776   -1.2897   -0.7928
    0.0673   -0.3588   -0.1418
    0.4143   -0.1886    0.6229

>> 

However, doublicating variables (e.g. to keep a better overview) is not so bad as it might be in other languages (in regard of memory wasting). Matlab uses copy on write - see https://en.wikipedia.org/wiki/Copy-on-write and http://www.matlabtips.com/copy-on-write/

And - afaik - octave too:

octave:1> memory

 Memory used by Octave:   24.4414 MB 
 Physical Memory (RAM): 7586.74 MB 

octave:2> tic, m=rand(10000,10000); toc
Elapsed time is 5.52749 seconds.
octave:3> memory

 Memory used by Octave:   787.531 MB 
 Physical Memory (RAM): 7586.74 MB 

octave:4> tic, n=m; toc
Elapsed time is 4.19617e-05 seconds.
octave:5> memory

 Memory used by Octave:   787.535 MB 
 Physical Memory (RAM): 7586.74 MB 

octave:6> whos
Variables in the current scope:

   Attr Name        Size                     Bytes  Class
   ==== ====        ====                     =====  ===== 
        m       10000x10000              800000000  double
        n       10000x10000              800000000  double

Total is 200000000 elements using 1600000000 bytes
Markus
  • 2,998
  • 1
  • 21
  • 28
  • On the MAT vs. Oct part: wacky; thanks for the comparison. I got the cell-array-list syntax `[a,b,c,d] = C{:}` from [the MATLAB docs](http://www.mathworks.com/help/matlab/ref/deal.html)... indexing of "anonymous" cell-arrays won't work in MAT...? My Octave was missing memory.m; found [here](https://github.com/markuman/linux/blob/master/octave/memory.m). After the above, I set one element of n as `tic, n(1234,2345)=42; toc` takes ~1sec and then `Memory used by Octave: ...` doubles -- CoW indeed! Thanks for the tips. – hoc_age Jun 13 '14 at 20:11