11 comments

[ 4.6 ms ] story [ 32.3 ms ] thread
This sounds exactly like the semi-secret language that's been floating around in my head for months!
Thanks so much for posting this, it brings back fond memories of playing IF games as a kid (wish I still had that much free time on my hands). Saved to InstaPaper for later reading.
Speaking of Prolog, I often run into situations where I would love to have some semi-dialect of prolog available at runtime (ie: use regexes for simple string problems, use prologexes for simple logic problems).

Are you aware of any prolog-like languages that integrate well with other programming languages?

Implementing a toy Prolog is a common task in intermediate-level Lisp textbooks. Both "On Lisp" and "Paradigms of Artificial Intelligence Programming" are good examples.
I don't know of any (outside of semi-toy Prologs in _On Lisp_ and PAIP), but writing a Prolog dialect designed for embedding (in a similar manner to Lua) is near the top of my list of future projects. Prolog can be really awkward for some things (most notably IO / side effects), but for certain problems, its approach is an excellent fit.

Constraint programming (often bundled with Prolog) also deserve far more attention, IMHO.

For CP, GECODE is C++, which makes it very easy to bundle /if/ you're writing in that language.

SWI-Prolog can be used embedded - but I haven't any experience with the results.

I'm reading Guido Tack's thesis now, actually, trying to get a better sense of how constraint systems are implemented.

SWI is my usual Prolog runtime, but I haven't tried running it embedded. I really like Lua's design principle of, "The language doesn't handle this particular thing well, but since it's embedded, it doesn't need to - keep the language small". A mini-Prolog could focus on what it does best, have a simple C API, and leave the rest to the surrounding language.

The backward subject-verb semantics in the OO examples are typical anti-OOP straw men. It doesn't have to be Room.look() and Object.examine(), when it could simply be Player.look(Room), Player.examine(Object), Player.put(Meat, Basket), etc. Don't begin with a design pattern then write code around that poorly choosen pattern. Instead write your core logic expressions first then it becomes obvious what the structure of each object ought to be.
The concept that all OO is based around message-passing is almost an anti-OO straw man, except that message-passing is still considered to be the 'default' OO style. It's hard to call it a straw man when even the experts seem to take it for granted.

OK, so what would I propose? CLOS-like generic methods with full multiple dispatch and specialization.

That would solve the problem you solve with the 'Player.put(Meat, Basket)' syntax by replacing it with 'put(Meat, Basket)' or, at worst, 'put(Player, Meat Basket)'. The advantage of this is that every time you need to put a new kind of thing, you only have to update one method, as opposed to updating the 'put()' method in everything that knows how to 'put()'.

In CLOS, methods dispatch on all their arguments. There is no special God Object or God Class that knows way too much about what's going on, as your Player class would seem to. This is achieved by specializing the methods: Creating a new method with a different type signature for each object combination it will have to handle. As a result, each class of functions knows what it has to know, and objects are just places to store data with type information attached.

However, this might be the case of the good being the enemy of the best: Obviously, a good domain-specific language is an absolute maximum for any problem domain, and I7 is a good text-adventure DSL. Moving from Javascript to Common Lisp wouldn't be nearly as good of a deal.