Skip to content

Instantly share code, notes, and snippets.

@randrews
Created April 1, 2011 05:46
Show Gist options
  • Save randrews/897798 to your computer and use it in GitHub Desktop.
Save randrews/897798 to your computer and use it in GitHub Desktop.
Make Lua look like Prolog!
----------------------------------------------------------------------------------------------------
--- Making Lua look like Prolog:
---
--- Let's use metatables for something other than emulating prototype-based OO. By making the
--- __index metamethod create values for undefined things, we can make Lua look like Prolog!
--- We create empty tables for anything starting with a capital letter, functions that populate
--- those tables for lowercase things (to assign relationships) and if a name begins with "is_"
--- then it becomes a function that queries those tables.
----------------------------------------------------------------------------------------------------
setmetatable(_G,{ __index =
function(globals, name)
if name:match("^[A-Z]") then -- entity
rawset(globals, name, { })
elseif name:match("^is_") then -- predicate
local pred = make_predicate(name)
rawset(globals, name, pred)
else -- rule
local rule = make_rule(name)
rawset(globals, name, rule)
end
return rawget(globals, name)
end })
function make_predicate(name)
local rule = name:match("^is_(.*)")
return function(a, b)
return b[rule] == a
end
end
function make_rule(name)
return function(a, b)
a[name .. "_of"] = b
b[name] = a
end
end
----------------------------------------------------------------------------------------------------
--- Example: ---------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
father(Vader, Luke)
father(Vader, Leia)
friend(Vader, Emperor)
friend(Emperor, Vader)
friend(Han, Luke)
friend(Luke, Han)
brother(Luke, Leia)
sister(Leia, Luke)
assert(is_father(Vader, Luke))
assert(is_sister(Leia, Luke))
assert(is_friend(Han, Luke))
assert(is_friend(Luke, Han))
assert(not is_friend(Vader, Luke))
assert(not is_friend(Han, Jabba))
@wesleywerner
Copy link

wesleywerner commented May 22, 2020

I have your post on this bookmarked and always refer to it when I feel like a bit of Lua inspiration, it is a fine example. Today I noticed the code blocks are no longer rendered on the page at http://www.playwithlua.com/?p=5

As an aside -- you don't need the assignment of a[name .. "_of"] = b in the make_rule function. The "_of" value gets clobbered by each call but since it is not used for relationship testing it's existence is moot.

@randrews
Copy link
Author

@wesleywerner I updated the versions of all the plugins and wordpress a few days ago, and that broke a few things. One of the things it broke completely was the graphviz plugin, I migrated the site to a new host to fix that. But I didn't notice that it also broke my syntax-highlighting-pre-tag plugin, thank you for noticing! That post should be fixed now, I'm about to go through and fix the others.

(good news is the reason I updated everything is I'm about to start making some posts again)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment