Contruct filter expression within loop

Hi all,

I’m trying to simplify this code using a macro, but I’m pretty new to meta-programming and not sure what I need to do. I have an array bigrams of structs that have two fields (among others): w1, and w2 (both integers).

I want to write a loop that does the following:

# First iteration:
rows_with = filter(x -> x.w1 == 1, bigrams)
rows_without = filter(x -> x.w2 != 2, rows_with)

# Second iteration:
rows_with = filter(x -> x.w2 == 2, bigrams)
rows_without = filter(x -> x.w1 != 1, rows_with)

How can I dynamically write something like x -> x.w1 == 1 and x -> x.w2 != 2 within the loop? Is it good style? And would this work if it’s wrapped within a function (so no global scope for variables)?

It is not clear what you want there. Probably you don’t need macros, but it is also unclear what’s wrong about the solution you are providing.

Assuming that what you are asking is how do iterate over sets of functions, you could do something like this in this example:

    for (f1,f2) in [ # vector of tuples of functions
        (x -> x.w1 == 1, x -> x.w2 != 2), 
        (x -> x.w2 == 2, x -> x.w1 != 1)
    ]
        rows_with = filter(f1, biggrams)
        rows_without = filter(f2, rows_with)
    end

Depending on the purpose, that might be fine. Maybe more details are needed to really understand what you need, but in principle I don’t see why use macros (you’ll almost never need to).

1 Like

As @lmiq said, more information would be helpful.

Perhaps getfield could be useful in your case? It allows you to get a field value programmatically with Symbols, without the need to hard-code the field names:

struct Foo
  w1::Int
  w2::Int
end

obj = Foo(1,2)

for fname in [:w1, :w2]
  getfield(obj, fname) |> println
end

EDIT: By hard-coding, I just mean writing obj.w1 which has the field baked in. getfield(obj, fname) can just use a variable with the field name.