在supercollider中,“*”、“#”、“_”的作用是什么?

In supercollider, what's the role of "*", "#", "_"?

我最近一直在阅读大量关于 SuperCollider 的教程和论坛,并且偶然发现了一些使用 *# 以及 _ 的代码示例,但我不找不到为什么要使用它们?有人可以向我解释一下吗?这与避免多渠道扩张有关吗?

一些示例:

(
var list = [1, 2, 3];
func(*list);  // equivalent to func(list[0], list[1], list[2])
)

var a, b, c;
#a, b, c = [1, 2, 3]; // equivalent to a=1; b=2; c=3;

p = Pbind(
    \degree, Pwhite(-7, 12, inf),
    \dur, Pwrand([0.25, Pn(0.125, 2)], #[0.8, 0.2], inf),
    \legato, Pfunc { ~legato }    // retrieves value set by MIDI control
).play;
)

或(在Pseq

(
Pbind(
    \mtranspose, -1,
    \octave, 5,
    [\dur, \degree], Ptuple(y.collect(Pseq(_, inf)))
).play
)

阿斯特里克斯

您的示例快速显示了其工作原理的摘要,但让我们稍微扩展一下并定义一个三参数函数:

f = { arg a, b, c;
a + b + c;
};

当我们想调用函数时,我们可以这样做:f.value(1,1,1),其中returns 3.

现在说出于某种原因我们有一个包含三个数字的数组,我们想将它们传递给函数。

a = [1, 1, 1];

如果我们只是尝试 f.value(a) 我们只是一个错误。我们可以通过指定 f.value(a[0], a[1], a[2]) 来解决这个问题,或者我们可以使用 * 快捷方式。这会将数组分解为一个列表以传递给函数。所以等效的,更短的语法是 f.value(*a)

英镑

pound/hash 标志(无论你怎么称呼它)可以有两种不同的含义,具体取决于它的位置。让我们从一个数组开始:

a = [1, 2, 3];

假设您有三个变量并且希望它们获取数组内容。你可以这样做:

b = a[0];
c = a[1];
d = a[2];

但这需要大量的输入,所以等效的快捷方式是

#b, c, d = a

#的另一个含义是它出现在数组的左括号之前。根据尼克柯林斯的说法:

A note about efficiency

偶尔会看到

 #[1,2,3] //makes a totally fixed (non-dynamic) Array and is slightly cheaper, especially where you're not going to change the Array once you make it

而不是

 [1,2,3]    //a dynamic array 

显示差异

 a= #[1,2,3];
 
 
 a[0] //works
 
 
 a[0] = 8 //fails, because it can't be changed

(来自 https://composerprogrammer.com/teaching/supercollider/sctutorial/Technicalities/02%20Arrays.html

下划线

下划线正在做一些叫做部分应用的事情。它有一个帮助文件:https://doc.sccode.org/Reference/Partial-Application.html

它正在做的是替换参数声明和用法。所以在他们的一个例子中,你可以写:

(1..10).collect({ arg n; n.squared });

或者您可以稍微缩短它:

(1..10).collect( _.squared );

所以 _ 正在接管 n 的声明和使用。请注意,_ 还意味着您不使用 {} 括号。在您的示例代码中, Ptuple(y.collect(Pseq(_, inf))) 可以重写为 Ptuple(y.collect({arg z; Pseq(z, inf)}))

语法快捷键

所有这些快捷方式统称为“语法糖”。有一个名为那个的帮助文件,但如果你只是在学习 SuperCollider,我建议你暂时避免使用它,只有当你遇到一个符号在做一些奇怪的事情时才去尝试。