Suitably Impressed with Ruby

Ovid on 2008-05-21T14:06:58

Yes, I know you can do this with Perl and overloading, but in Ruby, this is built in to the language. First, here's some Prolog:

mortal(X) :- man(:X).
man(socrates).

The to find out who is mortal:

? - mortal(WHO).

Someone has created a tiny Prolog in Ruby and to do the same query above, you do this:

mortal      = Pred.new(:mortal)
mortal_goal = Goal.new(mortal, [:X])

man         = Pred.new(:man)
man_goal    = Goal.new(man, [:X])
mortal_goal.fact(man_goal)
Goal.new(man, ['socrates']).fact
query Goal.new(mortal, [:Y])

(Note: That took me a while to figure it out. Aside from dabbling, I've never really used Ruby before today. Now I'm trying to port a predicate logic engine. I'm not too bright.)

Of course, that's pretty painful. So they've redefined bits of Ruby (as they apply to their objects, so it's not global) and now they can issue the query like this:

mortal[:X] <<= man[:X]
man["socrates"].fact
query mortal[:Y]

That's pretty impressive. I wish Perl has symbols. Right now, I'm trying to fake it with an object, but it's not as easy.


Inline?

dagolden on 2008-05-21T16:50:31

Seems kind of nutty to write a bunch of stuff that approximates Prolog when the Prolog is designed for what it does and reads more easily.

Makes me wonder if some sort of Inline::Prolog isn't a better way to go. Parse a bunch of Prolog, interpret it and spit out a "query" sub.

--dagolden

Re:Inline?

Ovid on 2008-05-21T19:43:13

Already I've talked to a couple of folks who thought they could do that. Then they saw what it entailed. Apparently it's much harder than it sounds. I wouldn't know.

That being said, I want to be able to use real Perl data structures with predicate logic. That gives me the ability to open up doors that Prolog has a lot of difficulty with. It also means that AI::Prolog also won't cut it.

This solution is fairly small, fast, and doesn't require an interpreter for another language.

symbols?

Eric Wilhelm on 2008-05-21T19:43:06

IIRC, ruby symbols are just constant strings quoted by a leading ':'. So, please explain how my understanding is wrong or how perl's string quoting is leaving you wanting.

Re:symbols?

Ovid on 2008-05-21T20:38:15

Symbols are extremely lightweight and fast. Also, you can check for one with Symbol === some_var. In Perl, if you're using a quoted string, you don't get that, so you pretty much have to bless a reference to get the distinction. At that point, there's enough overhead that it's just not worth the point.

Re:symbols?

Eric Wilhelm on 2008-05-21T21:18:09

So, you just want the optimization of comparing a constant memory address ala \&::X?

    use warnings; use strict;
    my $q = \&::thing; my $v = \&::thing;
    warn $q == $v;
    warn $q == \&::thing;
    package bar;
    warn $q == \&::thing;

Thus, perl has symbols. Yeah, so our sigils are a bit hairier, but that makes us cuddly.

(Aside: if you want to play the package game, you can leave out the colons, but IIRC ruby only has absolute symbols.)

(Soliloquy: yeah, our symbols aren't terribly constant, but neither are our constants.)

Re:symbols?

Ovid on 2008-05-21T21:34:51

Part of the point of a symbol appears to be that you can easily recognize it as a symbol. Not so with the references above. You can't distinguish those from any other types that easily unless you bless them into their own class. Symbols in Ruby (someone stop me if I'm talking rubbish!) aren't just some funky constant. They're a way of making an extremely lightweight, constant identifier that is easy to pass around. It seems like a variable with no value. Sometimes you just want a guaranteed identifier to mark something.

Symbols in Perl6, sort of

davegaramond on 2008-05-21T23:38:52

As an aside, Perl6 also doesn't seem to support symbols a la Ruby. But perhaps one can use the 36 radix form of number literal e.g. :36, :36. It's supposed to be ultra-fast cause it's nothing but number. But the caveats are: it's case-insensitive, you can insert "_" and 0 prefix without changing its value. But I think it's good enough and also rather cute.

Re:Symbols in Perl6, sort of

davegaramond on 2008-05-21T23:43:49

Sorry, the formatter ate my symbols. Pretend [] are the correct braces: :36[MySymbol1], :36[Your_Symbol2].

The "_"-insensitiveness can (and should) be viewed as a feature :-)

The question is though...

Alias on 2008-05-22T03:08:24

... is it fast enough to be useful?

As we discovered when I tried to use AI::Prolog in a "real application" last year, it's one thing to be able to do the work, it's another thing entirely to be able to do it fast enough to be actually useful.

Ruby is already famous for being slow because of all the layered abstraction, is their implementation of that logic stuff fast enough to implement, for example, a 100 guest "dinner party problem" solution in a reasonable time?

Re:The question is though...

Ovid on 2008-05-22T07:37:00

My reply became long enough that I have a dedicated post about benchmarking the Ruby and Perl implementations. Short answer, it's a hell of a lot faster, but depending on your constraints, you still would have problems doing the "100 guest" dinner party.

What is the dinner party problem?

btilly on 2008-05-22T21:17:10

I didn't recognize the phrase, so I googled for it and got too much. If I tried to add Prolog to the query all I got was your post.

So I have to ask. What is the problem?

Re:What is the dinner party problem?

Ovid on 2008-05-22T21:34:17

I don't know if there is an exact problem, per se, but I assume it's like any other scheduling problem. You have lots of guests and ...

  • Bob has a restraining order against Alice.
  • Alice has a crush on Tim.
  • Tim has a crush on Bob.
  • William is violently homophobic.
  • Sarah is a vegetarian.
  • ... and so on.

And you have to find seating and dinner arrangements which are suitable for everyone. It is, as you know, a potentially very difficult problem.

Re:What is the dinner party problem?

Aristotle on 2008-05-23T01:07:09

Gosh, what examples. :-)