Personally, I'm not super excited about this idea. -- John
On Jun 11, 2014, at 9:13 PM, Andrew Simper <[email protected]> wrote: > So just to post again to make things clearer, right now algorithms tend to > look pretty ugly and obfuscated since you have to prefix function arguments > with the argument names using dot notation: > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > local v1::Float64 = coef.g0*state.ic1eq - coef.g1*state.ic2eq > local v2::Float64 = coef.g1*state.ic1eq + coef.g0*state.ic2eq > SvfSinOsc (2*v1 - state.ic1eq, 2*v2 - state.ic2eq) > end > > > This is a lot more readable to me, and it would be super useful to have a > "using" type operation similar to namespace but it could run on variables > instead, so that although writing the following is equivalent to what is > above, it is much easier to see what is going on: > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > using state, coef > local v1::Float64 = g0*ic1eq - g1*ic2eq > local v2::Float64 = g1*ic1eq + g0*ic2eq > SvfSinOsc (2*v1 - ic1eq, 2*v2 - ic2eq) > end > > What are peoples opinions on this? Would anyone else find it useful? > > > > On Friday, June 6, 2014 3:17:31 PM UTC+8, Andrew Simper wrote: > In implementations where you want named data, I've noticed that the algorithm > gets obfuscated by lots of variable names with dots after them. For example, > here is a basic analog model of a state variable filter used as a sine wave > generator: > > immutable SvfSinOscCoef > g0::Float64 > g1::Float64 > end > immutable SvfSinOsc > ic1eq::Float64 > ic2eq::Float64 > end > function SvfSinOscCoef_Init (;freq=1.0, sr=44100.0) > local g::Float64 = tan (2pi*freq/sr) > local g0 = 1.0/(1.0+g^2) > SvfSinOscCoef (g0,g*g0) > end > function SvfSinOsc_Init (startphase::Float64) > SvfSinOsc (cos(startphase), sin(startphase)) > end > > But the tick function looks a bit messy: > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > local v1::Float64 = coef.g0*state.ic1eq - coef.g1*state.ic2eq > local v2::Float64 = coef.g1*state.ic1eq + coef.g0*state.ic2eq > SvfSinOsc (2*v1 - state.ic1eq, 2*v2 - state.ic2eq) > end > > > It would be really cool if there was a way to shorthand the syntax of this to > something like the following, which is a lot more readable: > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > using s, c > local v1::Float64 = g0*ic1eq - g1*ic2eq > local v2::Float64 = g1*ic1eq + g0*ic2eq > SvfSinOsc (2*v1 - ic1eq, 2*v2 - ic2eq) > end > > > Lots of algorithms have arguments with the same type, but even then you could > still specify using just the most used argument, but if it doesn't help make > things more clear or isn't useful then people don't have to use it at all. > > > > Another pattern that would be nice to handle cleanly is: fetch state to > local, compute on local, store local to state. I have written code that > generates code to handle this since it is such a pain to keep everything in > sync, but if there was some way to automate this at the language level then > it would really rock, so here is an example of the longhand way, which isn't > too bad for this example, but just imagine if there are 20 or so variables, > and you are writing multiple tick functions: > > type SvfSinOsc > ic1eq::Float64 > ic2eq::Float64 > end > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > local ic1eq::Float64 = state.ic1eq > local ic2eq::Float64 = state.ic2eq > for i = 1:100 > # compute algorithm using local copies of state.ic1eq and state.ic2eq > end > state.ic1eq = ic1eq > state.ic2eq = ic2eq > return state > end > > > I have a feeling that macros may be able to help out here to result in > something like: > > function tick (state::SvfSinOsc, coef::SvfSinOscCoef) > @fetch state > for i = 1:100 > # compute iterative algorithm using local copies of state.ic1eq and > state.ic2eq > end > @store state > return state > end > > But I'm not sure how to code such a beast, I tried something like: > > macro fetch(obj::SvfSinOsc) > return quote > local ic1eq = obj.ic1eq > local ic2eq = obj.ic2eq > end > end > > macro store(obj::SvfSinOsc) > return quote > obj.ic1eq = ic1eq > obj.ic2eq = ic2eq > end > end > > dump(osc) > macroexpand (:(@fetch osc)) > macroexpand (:(@store osc)) > > SvfSinOsc > ic1eq: Float64 1.0 > ic2eq: Float64 0.0 > > Out[28]: :($(Expr(:error, TypeError(:anonymous,"typeassert",SvfSinOsc,:osc)))) > > > > > > >
