* in Pbind alternative syntax

Hi. There is a subtlety in the syntax for writing Pbind that I would like to understand. It is common to see Pbind keys written in two different ways:

  • Using symbols: Pbind(\instrument, \default, \note, 0)

  • Using the alternative syntax, mentionned in the Help File, and used in various examples taken from the web: Pbind(*[instrument:, \default, note:, 0])

From the information I collected so far, the * preceding the array is employed only for this particular use-case. Using it elsewhere, outside a Pbind, is almost guaranteed to fail. However, I haven’t found anything written about the meaning or the nature of that particular array construct.

Is it possible to call a function that will turn a regular array in a starred array? What is this type of array in the first place? Is it possible to find a way to reproduce this starred-array syntax elsewhere for building a new alternative syntax for Pbinds ?

I suppose that this behavior must be well understood by some of you who are accustomed to deep-diving in the SuperCollider source code. I would be glad to hear your thoughts about it, as it may be helpful for future documentation about Pbind.

3 Likes

Hi,

It’s a way of passing the elements of an array as single arguments to methods. So it’s not Pbind-specific, but useful also for example when evaluating a function:

f = { |one, two, three ...args|
	one.debug("first argument");
	two.debug("second argument");
	three.debug("third argument");
	args.debug("other arguments");
};

//This works
f.value(*[1, 2, 3])
//And this
f.value(1, 2, *[3, 4, 5])
//Not this
f.value(*[1, 2], 3, 4, 5)

In your Pbind example you define key-value pairs inside the array. As far as I know it’s just an alternative way of writing the array, so in my example I could use the following notation:

f.value(*[a: 2, b:3])

which is the same as

f.value(*[\a, 2, \b, 3])

Following the mechanism you just described, could there be a way to turn an array into a Pbind? Here is a short example to demonstrate what I’m thinking about :

[instrument: "default", note: 0, dur: 0.25].pbind ?

I would love to be able to do just that to quickly prototype patterns in a live-coding context. I already created some syntactic shortcuts for various pattern objects such as : [2,4].e for an infinite Pborklund2, [2,3,4,5,6].pseq for an infinite Pseq and [2,3,4,5,6].pseq1 for a one-time event, etc…

I created these shortcuts as the need for a more concise syntax arised when dealing with lots of Pbinds in a ProxySpace. Some supplementary syntactic sugar tricks are already provided by some Quarks such as miSCellaneous_lib with EventShorcuts.on.

Sure. A class extension like this should work:

+ Array {
	pbind {
		^Pbind(*this)
	}
}
2 Likes

That is it. It’s really that simple, ahahah. Thanks a lot. I’ll try to improve this simple extension in order to glue it more tightly with a ProxySpace based workflow.

One thought about the name: conversion from one type of object to another is often written with an “as” method: asString, asInteger, asArray, asSignal… so asPbind might be better for consistency (and IMO readability). (As a personal extension, of course, you can name it as you like.)

However, comparing concision by removing the contents:

  • Pbind(*[]) = 10 characters
  • [].pbind = 8 characters

… which doesn’t save much typing (where .pseq drops parentheses and , inf so the savings are more substantial). Perhaps in this case, the benefit is more to reduce visual noise (two layers of brackets and the * in the canonical syntax).

hjh

1 Like

.pbind does allow you to write [key:value] saving you from writing [\key, value] with the symbol notation, also eliminating the space after the colon still seems more readable to me than removing the space after the comma…plus you can do additional pre-processing on the key-values before setting them in the resulting Pbind…i suppose one could also shorten the extension to just “.p” for maximum terseness

Exactly. The code buffer can very quickly look cluttered with two or three patterns written using the traditional syntax. The array-based version I’m trying to use also have some drawbacks: deep nesting, method chaining, etc… For classical algorithmic composition in non real-time, I think it’s better to rely on more verbose abstractions.

There is an other hidden benefit of the array approach for users of non-qwerty based keyboards. Some symbols can be hard to reach, leading to a mechanical speed decrease, even for people that type really fast. On my actual keyboard configuration, using backslash is rather slow, and it is necessary by default for symbols in SCLang. The curved brackets {} are accessible through the AltGr + TY combo, and so is ~ with another AltGr based combo.

I’ve noticed that it is slightly easier to live-code on a qwerty-based keyboard simply based on the fact that programming languages and computer keyboards were designed with a subset of american english as reference (+ no accents, + a more rational distribution of symbols and numbers).

I haven’t tried yet but it might be possible to go one step further by playing with the interpreter. Correct me if I am wrong, but it might be possible to translate the array ["myPat", instrument: "default", note: 0].p or [instrument: "default", note: 0].p("myPat") to a Pbind nested in a Pdef or ProxySpace environment variable. The noise reduction and spared keystrokes could be substantial but I don’t really know if that’s a good idea.

I’m curious to know if you have some other tricks to play with patterns by writing less, or by writing in a more clever way.

i really like the extensions approach for creating a personal idiom. for myself i’ve developed some extensions that i can use like this:

'mysynth/1'.p(\degree, [0,1,2,3].pseq).play

which translates to

Pdef('mysynth/1', Pbind(\instrument, \mysynth, \degree, Pseq([0,1,2,3], inf))).play

so i think you can create a pretty fluid mini-dsl with extensions without even having to touch the pre-processor

True, but I was comparing Pbind(*[ ... ]) vs [ ... ].pbind, so there is no difference except dropping the star and the parens. All the other things you mentioned are the same for both.

I can agree that backslashes can be visually noisy and a bit harder to type in some layouts.

No objection to extensions for convenience! Malleability is one of the great things in SC.

As a tangent, a big weakness in live coding is the fact that most editors’ cursor navigation is clumsy and highly underdeveloped. The IDE has some particularly inefficient behaviors here – in many cases mixing alphanumerics and punctuation, I’ve seen ctrl-left/right move character by character (nothing close to word movement); or \symbols and ~envVars behave inconsistently wrt ctrl-shift-arrow selection or ctrl-backspace (one of them includes the punctuation in the token while the other does not); and there’s no good way to skip over bracketed blocks. Much live coding research focuses on syntax but I find I lose a lot of time in a live set just to pushing the cursor around. That seems to be neglected.

hjh

I like this extension you made. My only wish would be to push that Pdef / SynthDef identifier inside the array so they can stand out visually on the screen, with everything being wrapped behind square brackets.

Emacs and Vim are providing tools to jump in the text, push things, etc… I’m mostly using SCNVim, and I learned to use these modal text-editors for the sake of live-coding. There is something gestural about jumping around the text, pushing things, copying and pasting, etc…

That’s true but I don’t think that this is just a matter of sparing keystrokes. I see that as a way to imagine new ways to live-code music without the usual cognitive load associated with classical out-of-time programming. Most live-coding libraries are not proposing shortcuts but metaphors for the things you manipulate (agents for IXI Lang, Cycles for Tidal, Live Loops for SP), etc… I was surprised to find out that this idea is also very old, with HSML being an example of a rather “ancient” live-coding language that already played with the idea of manipulating simple mental objects such as shapes, etc…

The strength and weakness of SCLang is that everything is possible at the cost of building the appropriate abstractions. The pattern system is incredibely powerful but also very verbose because it tries to be as objective and unopiniated as possible.

In my (short) experience of the language, time was lost building the necessary scaffolding for music to happen. I really like what co¥ᄀpt did with his tutorial. He designed a small system embarking the musical objects he needed to create the kind of technical / rhythm-based club music he wanted to create.

1 Like

Preaching to the choir here…

It’s in the back of my mind to create an Emacs mode for my live coding dialect – but, not much bandwidth to dive into emacs-lisp these days.

I should file issues, though, for the dodgy navigation in SC-IDE. It’s pretty bad erm, well, better to say it like “not well tuned for SC syntax.”

hjh

1 Like

Hey, I found myself in this exact spot a while ago and coded some syntax sugar following this idea of extending the class. You can use my code (and extend it) if you like. I’m adding new patterns as I use them.

I also developed a custom class for easing out ProxySpace syntax, using function composition. It’s a wraper of @dkmayer’s miSCellanous_lib’s PLbindef, which allow for function composition and puts it inside an Ndef to be able to add effects using the same syntax. I built it without the intention of distributing it, mostly because all the hard work is done by @dkmayer’s wonderful quark, but you may take a peak at my solution if you want.
My approach is to create global variables with function composition syntax + array pattern extensions.

That’s exactly why I did it.
I’ve been using NeoVim and now Doom Emacs (with evil-mode) where typing is not an issue. So visual noise is just the thing.

I love chucklib. It’s been very inspiring to me.

Thank you for sharing your solution. I’ve been looking around on GitHub for solutions to the live-coding syntax problem on SuperCollider without finding yours until now. It seems that lots of people have developed idiosyncratic libraries by leveraging more abstract objects. Is there a video of the system in action or a “snapshot” of a live-coded performance? I really like the fact that you were able to integrate SuperDirt as well.

We ended up doing the same thing, and we are not the only ones. I guess that there must be something in the system pushing people to come up with this Array / String supplementary methods thing for live-coding.

It might be worthwhile to split this topic into a different one named like “Share your live-coding system” or something like that.

Sure, here’s one.
And here’s a 9-minute impro from scratch (in a shared stream - starting on minute 26:00)

Are there any videos of your performances available?

@loopier, I don’t mind at all if you distribute a wrapper class of PLbindef, I’d just ask for a mention. Some things to consider: if you’re adding to and/or varying my classes it would make sense to rename them (e.g. PLbindef2, PLbindefEnvironment2), that way taking care for the case someone is going to install both quarks. If you are not changing something – just using, maybe subclassing – it would be possible to define a dependency.

http://doc.sccode.org/Guides/UsingQuarks.html

You are right, sorry. I wasn’t planning to distrubute this class. I just made it for personal use, so I didn’t add all the licensing text because it’s just a playground for me. I just wanted to share my conceptual approach with @Bubo which seems to have a lot in common with what I was trying to achieve. That’s why I mentioned your authorship in the post. I’ll add it to the code now that I have shared it. My apologies.

EDIT: Just did it and pushed it.

no worries, all fine :slight_smile: just like to mention at this point: ironically, PLbindef is itself a wrapper class, based on the wonderful Pbindef, so credit to its author Julian Rohrhuber !

1 Like

I came here to understand the syntax of *[ ] but everything below first answer deals with another topic.

I just wanted to say I found this to be working too:

( 
var sequenceDur = 8;
var parameters = [
	instrument: \beep,
	dur: Pseq([3,3,2] / 8, inf),
	degree: Pseq([0, 2, 4, 6].scramble, inf),
	octave: Pdup(6,Pseq([3,4],inf)),
	legato: Pwhite(0.01,0.5),
	amp: 1
];

~pbindTest = Pfindur(sequenceDur, Pbind(*parameters));
)
~pbindTest.play;

the crucial part here is *parameters in Pbind which otherwise errors with Pbind should have even number of args.

Perhaps the rest of discussion should be moved under different title?