I realize this may be a silly question, but in my experiments with tidal and with the videos I've watched, I haven't seen references to implementing local functions and/or implementing local variables that are then used in patterns.
The reason why I ask is because it would be nice if you could have a melody stored in a variable, used in some permutations across different patterns, and then change the variable and then have that change reflected in the playing patterns. Additionally, if you could change that variable within a function and still have that change reflected in the playing patterns, that would be very nice.
I saw one possible technique from this @kindohm's amazing tidal tutorial: he defines expressions with the let keyword inside a do block.
In your case, I create an expression for a sequence of notes and then have both the original and the reversed played by the lead synth, and the stretched reversed version played by the bass:
do
let melodicSeq = scale "minor" "0 -1 3 2 7 5 4 -3"
d1
$ off 0.125 (rev)
$ slow 2
$ note melodicSeq
# s "juno:5"
# gain 0.8
d2
$ slow 4
$ rev
$ note melodicSeq
# s "bass1"
# legato 0.7
Yes I've been wondering if I should shift focus back to the userbase rather than trying to do this book.. But I'd really love to make progress on the latter, which should then feed back into the userbase. Edits to the userbase are always appreciated though!
Or maybe the two efforts should come together. I've been looking admiringly at this great system: https://www.pubpub.org/
I'm going to explore moving my tidal book efforts there, and then maybe the userbase could be merged with that somehow
Yeah, I had a look at pubpub after I saw you refer to it, very interesting. Meanwhile, I'm finding a bit more confidence in myself to chip away at the userbase wiki occasionally when I find something that needs doing.
thanks @tedthetrumpet, I think this is sort of low-level though and I saw that reading from hackage you can sometimes get slightly more information on the innards. But I found no information in either place. I will wait then
Thanks @yaxu - that makes sense - I'll fiddle with that sort of syntax and see what I can get out. What about my second question - having functions that can modify variables and theoretically, be tied to the clock somehow - is that something that exists ?
@mattia.paterna - thanks for the link to Kindohm's tutorial - that's definitely an interesting way of managing this state. Could definitely work well.
I'm trying to daisy chain a couple of concepts here, so my full thought process goes like this:
Have variables that are accessible by d1,d2, etc. and can change on re-evaluation.
Have functions that are tied to the clock and can either read variables and spit out a new variable or modify existing variables that are currently being read by the d1, d2, etc.
The first proof of concept I want to do with something like this is to create a cellular automata / game of life idea that will have rhythms and melodies constantly changing based on very simple interaction rules.
If that works, then what I want to be able to do is
Have midi input read by a function that in turn modifies a value, which is then read by d1,d2, etc. - essentially allowing for feedback loops that are modifiable in the real world and will interact in unpredictable, but stable ways.
That's kind of been my blocker, and I'm trying to figure out how or if that's possible.
Fwiw, I saw that in the upcoming learning sessions that there was some discussion of functions, I've bought the sessions and will be working my way through them. Hopefully they'll help answer some of the more basic stuff I've been asking.
Tidal's computational model of patterns has advantages and disadvantages. One disadvantage is that there is no internal state. A Tidal pattern is a pure function from time (and other external state) to events, and has no way of storing state within a pattern. This buys you flexibility, for example being able to reverse time. Furthermore you can usually work around this, for example by making patterns that wrap other patterns, manipulating their inputs and outputs.. But you can't really implement cellular automata as a tidal pattern, unfortunately.
@yaxu That makes sense and is consistent with how I was modeling the patterns in my head (e.g. as a pure function without state), but was hoping I was wrong I'll watch the teaching tidal series and hopefully glean some information about how to achieve something similar. Thanks!
would it be possible at some point have a thorough discussion about it?
Super interested, as I am approaching functional programming and I would really like to understand Tidal's core concepts.
(I just don't want to flood this discussion with things not related to the video.)
My understanding is that the patterns are pure functions within Haskell, which means that they are essentially immutable once they are evaluated ; this is why in the Kindohm example. the variable definition is part of the block, so that when the block gets re-evaluated, the variable gets re-evaluated and placed back into the patterns.
I haven't yet tested it, but I believe in Yaxu's example, if we define the variable and evaluate it into the pattern, if we change the variable and evaluate, its change won't be immediately reflected in any pattern that uses it - those patterns will each need to be re-evaluated. Is that a correct understanding ?
No in my example, you are setting some mutable state, which gets passed into the pattern by the scheduler via the same mechanism as MIDI/OSC input, so you do hear the results straight away. This is the "external state" I alluded to earlier.