В supercollider, какова роль «*», «#», «_»?

#supercollider

#суперколлайдер

Вопрос:

В последнее время я прочитал множество руководств и форумов по SuperCollider и наткнулся на некоторые примеры кода, использующие * and # и _ , но я не понимаю, почему они используются? Кто-нибудь может мне это объяснить? Связано ли это с тем, чтобы избежать многоканального расширения?

Некоторые примеры:

 (
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
)
 

Ответ №1:

Астерикс

В вашем примере быстро показано, как это работает, но давайте немного расширим его и определим функцию с тремя аргументами:

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

Когда мы хотим вызвать функцию, мы могли бы сделать: f.value(1,1,1) , которая возвращает 3 .

Теперь предположим, что по какой-то причине у нас есть массив из трех чисел, и мы хотим передать их функции.

 a = [1, 1, 1];
 

Если мы просто попробуем f.value(a) , мы просто ошибка. Мы могли бы обойти это, указав f.value(a[0], a[1], a[2]) или мы можем использовать ярлык * . Это разбивает массив на список для передачи функции. Таким образом, эквивалентный, более короткий синтаксис f.value(*a)

Фунт

Знак фунта / хэша (как бы вы его ни называли) может означать две разные вещи, в зависимости от того, куда он идет. Давайте начнем с массива:

 a = [1, 2, 3];
 

Допустим, у вас есть три переменные, и вы хотите, чтобы они получили содержимое массива. Вы могли бы сделать:

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

Но это требует много времени на ввод текста, поэтому эквивалентный ярлык

 #b, c, d = a
 

Другое значение # — это когда оно находится прямо перед открывающей скобкой массива. По словам Ника Коллинза:

Замечание об эффективности

Время от времени вы будете видеть

  #[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 Arrays.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, я предлагаю вам пока избегать его и погружаться в hen только тогда, когда вы сталкиваетесь с символом, делающим что-то странное.

Комментарии:

1. Спасибо. Прочитайте это внимательно. Действительно полезно. Многие примеры используют это, поэтому, даже если я пока не собираюсь использовать этот «синтетический сахар», мне нужно было понять это, чтобы понять примеры.

2. «_» по-прежнему не очень понятен. Если я выполняю 1.forBy(0.01,-0.01, { arg n; n.postln}); , у меня есть числа от 1.0 до 0.01. Если я выполняю 1.forBy(0.01,-0.01, { _.postln}); , у меня нет результата… :-/

3. Да, _ также не работает в соответствии с документацией для меня. Я думаю, что есть какая-то ошибка или другая проблема.

4. На самом деле это работает, но, как и многие вещи в SC, это сложно. «_» подавляет необходимость / запрещает фигурные скобки «{ … }» !!!!. Итак, мой пример должен быть переписан следующим образом: 1.forBy(0.01,-0.01, _.postln); (обратите внимание, что я удаляю { } ).

5. Спасибо @lvr123! Я отредактировал ответ, чтобы отразить информацию в вашем комментарии.