Skip to content

Instantly share code, notes, and snippets.

@goretkin
Last active April 23, 2020 00:48
Show Gist options
  • Save goretkin/55e5113513298c00082e040050c9fd7d to your computer and use it in GitHub Desktop.
Save goretkin/55e5113513298c00082e040050c9fd7d to your computer and use it in GitHub Desktop.
short circuit trivalent logic
import PrettyTables
macro and(p, q)
quote
vp = $(esc(p))
if !ismissing(vp)
if vp
$(esc(q))
else
false
end
else
if isequal($(esc(q)), false)
false
else
missing
end
end
end
end
macro or(p, q)
quote
vp = $(esc(p))
if !ismissing(vp)
if vp
true
else
$(esc(q))
end
else
if isequal($(esc(q)), true)
true
else
missing
end
end
end
end
function doit(case, andor )
results = []
for (p, q) in Iterators.product(ntuple(_->(true, false, missing), 2)...)
ep = 0
eq = 0
# make thunks to detect evaluation
tp() = begin; ep += 1; p; end
tq() = begin; eq += 1; q; end
r = try
if case == :sc # short-circuiting logic
if andor==:and; (tp() && tq()) ; elseif andor==:or; (tp() || tq()) ; end
elseif case == :lo # trivalent logic
if andor==:and; (tp() & tq()) ; elseif andor==:or; (tp() | tq()) ; end
elseif case == :both
if andor==:and; @and tp() tq() ; elseif andor==:or; @or tp() tq() ; end
end
catch e
e
end
result = (p=p, q=q, ep=ep, eq=eq, r=r)
push!(results, result)
end
# tighten types
map(identity, results)
end
for case = (:sc, :lo, :both), andor = (:and, :or)
@show case andor
PrettyTables.pretty_table(doit(case, andor))
println("---------\n")
end
# make sure behavior matches
for andor = (:and, :or)
@assert all(isequal.(getfield.(doit(:both, :and), :r), getfield.(doit(:lo, :and), :r)))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment