I am a huge fan of squeezeJoin. Naturally it is used with the inhabit function. I use this to create progressions and drum beats. It means, that you can control a pattern with a pattern like this:
do
let drum pt f = inhabit [
("1", f $ s "[bd(3,8), hh*4]" )
,("2", f $ s "[bd*4, ~ sn, hh*4 hh*8]" )
,("f1",f $ s "sn!2 bd!4 sn!2 tom:1! tom:0!" )
] pt
bubu = (fast "<1 1 2 1>" . ply "<1!3 1>" )
d1 $ drum "<1 2 1 f1>" (bubu)
And then you can decide whether you want to apply a function on the outer or the inner pattern. I have a custom implementation for this but basically I use it like in the code snippet above, i.e.
drums (inner_pattern_function "1") outer_pattern_function
For a live coding performance I use numbers to control a pattern, because it is really easy to change the numbers with a simple shortcut in NeoVim.