I don't think it warrants syntax, but might be nice in a macro. I've had cases where I just put my entire simulation state in a single object, so I don't need to give 100s of parameters to every object. In that case (where the object is more of a container than an abstraction), it might be nice to use.
On Thu, Jun 12, 2014 at 12:13 AM, Andrew Simper <andrewsim...@gmail.com> 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)))) >> >> >> >> >> >> >> >>