This "obfuscation" is also tedious with DataFrames.

I've been playing around with an `@with` macro to use symbols to
reference DataFrame columns. I extended that idea to several macros to
ease data manipulation:

https://github.com/JuliaStats/DataFramesMeta.jl

The tricky part with DataFrames and associative types is that the
types are not known ahead of time. Wrapping the code in the block in a
pseudoanonymous function gets around that issue. For DataFrames and
associative types, this also gives speed advantages because indexing
these is slow. I'm not sure if this approach could also cover mutable
and immutable objects.

Here is an example:

df = DataFrame(x = 1:3, y = [2, 1, 2])
x = [2, 1, 0]

@with(df, :y + 1)
@with(df, :x + x)  # the two x's are different

x = @with df begin
    res = 0.0
    for i in 1:length(:x)
        res += :x[i] * :y[i]
    end
    res
end

On Fri, Jun 6, 2014 at 3:17 AM, Andrew Simper <andrewsim...@gmail.com> 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))))
>
>
>
>
>
>
>

Reply via email to