#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! Я отредактировал ответ, чтобы отразить информацию в вашем комментарии.