Octave / MATLAB中deal()函数的作用是什么?

4

一些参考代码会简单地使用deal()函数,例如:

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

如文档所述(OctaveMATLAB),该函数仅将输入复制到输出。 在这种情况下或通常情况下,为什么要使用deal() 我正在尝试学习“更正确”的MATLAB/Octave用法,并想知道是否遗漏了重要内容。也许,这种用法...

  • 在编程中,我们通常使用习惯性的风格或成语来代替简单的赋值,例如 a=1, b=2, c=3 或者更为复杂的单元数组列表解包方式 [a,b,c] = {1,2,3}{:}。但是这种方式比 Python 中 参数解包 更加受限,就像在 这个问题 中所提到的那样。
  • 如果 deal() 用于处理复杂/可变参数,则可以用一些更为优雅的特性,例如 "深拷贝" 和 "浅拷贝",如果这里真的存在这样的概念的话?

我也明白单参数的 [a,b,c]=deal(42),但这本质上相当于 a=b=c=42,而 [a,b,c]=deal(x) 则是将 x 分配给所有变量,而不是将 x 的元素分配给每个变量。

或者只是因为我过度思考了这个函数的微不足道的用法。


1
这是一个非常简单的函数,输入“edit deal”并查看代码即可。你不需要deal,我从未使用过它,也从未错过它。 - Daniel
1
我猜你自己回答了这个问题。据我所知,使用deal()的唯一原因就是为了可读性。你提出的“深拷贝”和“浅拷贝”的问题在这里是无关紧要的(至少在Octave中),因为解释器足够聪明,能够检测到a = b需要实际上在内存中进行复制。 - juliohm
在C语言中有类似的函数吗? - Bryson S.
@BrysonS. - C语言没有类似的函数,原因有几点。MATLAB的“deal”函数接受各种输入(标量、逗号分隔列表、单元数组、结构体数组访问器等),因此您需要执行类似于标记联合的操作。或者您可以使用一些奇怪的可变参数或C++内容。多个输出值是一个问题,因此您必须返回数组、结构体或指针等,但这似乎过于复杂。应用是什么? - hoc_age
2个回答

6

我偶尔使用deal的一种非常有用的方法是创建匿名函数返回多个输出参数。例如:

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

编辑:由于人们认为这种模式可能有用,需要注意一个问题,即您必须返回完整的输出数量。特别地,您不能使用a = f(3),否则会出错。要检索单个输出,请使用[a,〜] = f(3)[〜,b] = f(3)。抑制输出参数的语法已经存在大约自R2007a以来(我恐怕无法确切地记得何时)-在较旧的版本中,您将需要始终返回两个输出。希望对您有所帮助。


1
确实很聪明,我并没有立即看到其他的做法;尝试一些索引和cs-list似乎不起作用。这应该放在匿名函数deal的文档中! - hoc_age
在C语言中有类似这样的东西吗? - Bryson S.
@BrysonS。——请查看我在问题本身下面对您类似评论的回复。 - hoc_age

3

首先,你所提供的示例在Octave中可以工作,但不能在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.

如何以及何时使用deal()无法概括。这取决于您的脚本、数据结构、您想要做什么以及结果应该如何等因素。
>> 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));
>> 

因此,一些函数的设计中nargout = 1,您可以轻松地将输出分发到“一行”中的多个变量中。

如果一个函数有多个nargouts,那就有趣了。

>> [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

>> 

然而,在Matlab中复制变量(例如为了更好地进行概述)并不像在其他语言中那样糟糕(涉及内存浪费)。Matlab使用写时复制 - 参见 https://en.wikipedia.org/wiki/Copy-on-writehttp://www.matlabtips.com/copy-on-write/。而且据我所知,Octave也是如此:
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

在MAT与Oct部分:有点古怪;感谢比较。我从 MATLAB文档中得到了cell-array-list语法[a,b,c,d] = C {:}...“匿名”单元数组的索引在MAT中不起作用...?我的Octave缺少memory.m; 在这里找到了它。在上述操作之后,我将n的一个元素设置为tic,n(1234,2345)=42; toc需要约1秒钟,然后Octave使用的内存:...翻倍--确实是CoW!感谢您的建议。 - hoc_age

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接