Help with macro to construct truth tables

Sorry, for the misunderstanding, I thought there was a missing chunk.

I wasn’t talking about escaping, I was talking about the difference between

:(($(args...),))

and

:(($(args...,)))

To in your code, the problem is that when you write

:(@show $vars, $expr)

this doesn’t do what you want:

julia> let vars = [:x, :y], expr=:(x && y)
           :(@show $vars, $expr)
       end
:(#= REPL[91]:2 =# @show ([:x, :y], x && y))

here we see there’s a vector of Symbols in here instead of what you wanted. This can be re-written as

julia> let vars = [:x, :y], expr=:(x && y)
           :(@show [$(vars...)], $expr)
       end
:(#= REPL[92]:2 =# @show ([x, y], x && y))

to now get a vector of x and y. Though, for efficiency, you likely are better off writing

julia> let vars = [:x, :y], expr=:(x && y)
           :(@show ($(vars...),), $expr)
       end
:(#= REPL[93]:2 =# @show ((x, y), x && y))

to get a Tuple of values instead.

Here’s the revised macro:

julia> macro truth_table(expr)
           # Walk the expression and push the variables found to a vector `vars`:
           vars = Vector{Symbol}() # the `[]` wasn't necessary here.
           find_vars!(var::Symbol) = !(var in vars) && push!(vars, var)
           find_vars!(expr::Expr) = find_vars!.(expr.args)
           find_vars!(::Bool) = nothing

           find_vars!(expr)

           # Generate nested for loops where each variable is given a truth value:
           ex = :(@show ($(vars...),), $expr)  
           for i in reverse(vars)             # Take a variable (in the order they were found).
               ex = quote
                   for $i in (true, false)    # Iterate over truth values.
                       $ex                    # Nest the previous expression.
                   end
               end
           end
           return ex
       end # truth_table
@truth_table (macro with 1 method)

Now, we have

julia> @truth_table x && y
((x, y), x && y) = ((true, true), true)
((x, y), x && y) = ((true, false), false)
((x, y), x && y) = ((false, true), false)
((x, y), x && y) = ((false, false), false)

and

julia> @truth_table p || (q && r)
((p, q, r), p || q && r) = ((true, true, true), true)
((p, q, r), p || q && r) = ((true, true, false), true)
((p, q, r), p || q && r) = ((true, false, true), true)
((p, q, r), p || q && r) = ((true, false, false), true)
((p, q, r), p || q && r) = ((false, true, true), true)
((p, q, r), p || q && r) = ((false, true, false), false)
((p, q, r), p || q && r) = ((false, false, true), false)
((p, q, r), p || q && r) = ((false, false, false), false)
2 Likes