Title: Subroutines Post by: sciurius on May 18, 2020, 07:41:49 PM Reflecting on the 'Truncate and Subroutines'...
Code: Set Tempo 120 Finally a way to set a pattern and chord in one line. Title: Re: Subroutines Post by: bvdp on May 19, 2020, 02:12:06 AM I really like subroutines ... and we should try to used them more!
The only problem with them is that you can't have a variable number or arguments ... so in your case, you'd need a different sub for "Am", "Am / Gm /", etc. You could use macros to hold the chords and pass that to the subroutine, but that might be silly. I'm going to have to play with this and see if I can get it work. Maybe it already does ... way too much code here for me to remember what/why I've written. Title: Re: Subroutines Post by: bvdp on May 19, 2020, 03:29:53 AM What you think about introducing a grouping option? I'm thinking the ()s not used at this point ... so, we could say that stuff inside them are to be assigned to a subroutine arg. So, my earlier example:
Code: DefCall To54 chord would work fine using: Code: Call To54 (Am / Gm) /// 3 chords to CHORD Just a matter of taking the stuff in () and assigning it to "chord" as one chunk. Just now (and it's getting late) I don't see why this wouldn't work. Comments? Title: Re: Subroutines Post by: sciurius on May 19, 2020, 08:48:01 AM Quote I really like subroutines ... and we should try to used them more! Most certainly. We're programmers, after all :) . Quote The only problem with them is that you can't have a variable number or arguments ... I think we're hitting a very low-level design issue of MMA: the parser. Currently, source lines are split into whitespace separated items (let's call them 'words') immedeately after reading. This means you cannot write things like (in a sequence) 1.5 0 3-1:$LOUD since the macro needs to be a word. You cannot write (in the .mmarc) SetLibPath My Documents/mma unless you want your stuff in the folders "My" and "Documents/mma". Likewise, (Am G C) are three words, "(Am", "G", and "C)". You can artificially apply some heuristics on leading and trailing parens but it is clumsy and error prone. The same goes for good old strings, e.g. print "A B" will print two words, ""A" and "B"" instead of the (more logical) string "A B". A token based parser would be much better. I did some experiments but unfortunately (or maybe fortunately) I lost them... Using a tokenizing parser would have a drastic impact and probably break a lot of songs... Title: Re: Subroutines Post by: bvdp on May 19, 2020, 04:17:14 PM Yup.
If I were to start all over again I'd make different decisions. Unfortunately, MMA was really designed to be a very simple, super metronome and then morphed into the monster we now have. Still, it works pretty well. After all, how often do you need to print strings with quotation marks when creating a midi file? And that was then and we're now here in the present :) But, adding () to the subroutine code should be painless and useful. As always, give me a day or so. Title: Re: Subroutines Post by: sciurius on May 20, 2020, 06:26:15 AM I don't see the problem with multiple arguments. When called with several arguments you can slice:
DefCall MySub Arg print Arg = $Arg // all args print Arg 1 = $ARG[0] // first word of arg print Arg 2 = $ARG[1] // second word of arg ... Using multiple variables would be nice, though: DefCall MySub Arg1 Arg2 Arg3 print Arg 1 = $Arg1 print Arg 2 = $Arg2 ... Another option would be a special function, e.g. $_SUBARG(0) // number of words in arg $_SUBARG(1) // 1st word of arg $_SUBARG(2) // 2nd word ... This would allow looping over the arguments. Title: Re: Subroutines Post by: bvdp on May 20, 2020, 04:14:14 PM I don't see the problem with multiple arguments. When called with several arguments you can slice: DefCall MySub Arg print Arg = $Arg // all args print Arg 1 = $ARG[0] // first word of arg print Arg 2 = $ARG[1] // second word of arg ... Only problem here is that you need to know in advance how many args there are :) Looking (just looking!) at () is on the top of my pile of things to do. Title: Re: Subroutines Post by: bvdp on May 20, 2020, 04:33:42 PM Bugger, here I coded the [] code and then I forget about it :) So, for my original code the following works:
Code:
Neato :) Maybe I don't need to look at () after all (which would make my life much simpler!). Title: Re: Subroutines Post by: sciurius on May 20, 2020, 05:33:29 PM Given that slicing tries to follow python syntax it should be noted that $var[] should be invalid.
With the attached very simple patch to MMA/macro.py $var[] now returns the number of words in $var. Do we need more? Title: Re: Subroutines Post by: bvdp on May 21, 2020, 01:43:42 AM Actually, this is quite brilliant. We can now do something like:
Code:
Of course, it's no better than my earlier example and the if/then is completely redundant ... but taking actions inside a subroutine based on the number of arguments could be a lot of fun. I think there could be lots of uses for this in the future! I will post a new developer release in a few days ... hopefully, a new mainstream release will be "real soon now" as well. Thanks so much! Title: Re: Subroutines Post by: sciurius on May 21, 2020, 06:23:34 AM Title: Re: Subroutines Post by: bvdp on May 21, 2020, 04:19:40 PM Why not set numargs $Chord[] Aw, that'd be way to simple :) Of course, the other way around this is to add len() to the permitted ops in safe_eval ... but, I think leaving it as is will be just fine. Title: Re: Subroutines Post by: bvdp on May 21, 2020, 05:38:00 PM What is really nutty is that one really doesn't need to know the number of args for my little subrouting at all. Using:
Code: DefCall To54 chord Works just fine with any number of chords passed :) Title: Re: Subroutines Post by: bvdp on June 19, 2020, 02:22:42 AM I was adding this code to the "egs" directory for MMA and caught some faults :) This bit will work much better:
Code: DefCall To54 chord The only issue with this bit of code is that if you decide to use the "@" modifier to place the offsets of chords it will not work. I really hope this bit of code and discussion helps someone in the future. |