Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re^5: (why to use logic programming)

by BUU (Prior)
on Feb 14, 2005 at 19:37 UTC ( [id://430903]=note: print w/replies, xml ) Need Help??


in reply to Re^4: (why to use logic programming)
in thread Easy Text Adventures in Perl

What you say makes sense, as usual =], but I'm afraid I'm still having trouble thinking of specific examples where it would be better. You mention several fields such as AI and so forth, but the example you gave doesn't seem like that much of a win over an imperative language, unless I'm drastically missunderstanding it. Here is my interpretation of your prolog:
sub is_average { my $self = shift; if( not $self->foreigner and not $self->spouse and $self->income > 3 +000 ) { return 1; } }
Although I'm not sure where Income2 really enters in to it, perhaps my $self->income should return a list of incomes, but that's a minor detail, yes?

Replies are listed 'Best First'.
Re^6: (why to use logic programming)
by Ovid (Cardinal) on Feb 14, 2005 at 20:15 UTC

    Your example shows why logic programming beats imperative programming hands down (in this particular case). Let's flesh out my example. For the sake of simplicity, we'll just say average taxpayers are not foreigners, their spouses (if any) make less than 30000 and their income is less than 50000.

    foreigner(abdul). foreigner(marcus). spouse(edward, sally). spouse(bill, hillary). gross_income(hillary, 100000). gross_income(edward, 20000). gross_income(bill, 30000). gross_income(marcus, 49999). gross_income(mary, 35000). average_taxpayer(Person) :- not(foreigner(Person)), not(( spouse(Person, Spouse), gross_income(Spouse, Income1), Income1 > 30000 )), gross_income(Person, Income2), Income2 < 50000.

    So now it's trivial to find out if "marcus" is an average taxpayer (no) or if mary is (yes). You'd have to write a bit more Perl code than I would have to write Prolog code. However, this is the kicker. What if I want a list of all average taxpayers? Well, I know you have to have a gross income to be an average tax payer, so I issue the following query:

    gross_income(Person,_), average_taxpayer(Person).

    That will tell me that edward and mary are average taxpayers. I didn't have to write any extra code to do that. Logic programs can infer the answer. Perl would have a hard time keeping up with that. In fact, one of the fascinating things about logic programs is that they can all be reused in a similar manner. With imperative programming, reuse means "don't duplicate code." With logic programming, reuse means that, but it also means "use the same code to answer related but different questions."

    One thing to keep in mind about logic programming is that you're not looking at function calls. You're looking at relationship definitions and you don't have to write any extra code to express them.

    Cheers,
    Ovid

    New address of my CGI Course.

      So now it's trivial to find out if "marcus" is an average taxpayer (no) or if mary is (yes). You'd have to write a bit more Perl code than I would have to write Prolog code.
      Actually, you don't. It translates pretty straightforward:
      $foreigner{abdul} = 1; $foreigner{marcus} = 1; $spouse{edward} = "sally"; $spouse{sally} = "edward"; $spouse{bill} = "hillary"; $spouse{hillary} = "bill"; $gross_income{hillary} = 100_000; $gross_income{edward} = 20_000; $gross_income{bill} = 30_000; $gross_income{marcus} = 49_999; $gross_income{mary} = 35_000; sub average_taxpayer {my $Person = @_ ? shift : $_; !$foreigner{$Person} and not ($spouse = $spouse{$Person} and $income1 = $gross_income{$spouse} and $income1 > 30_000) and $income2 = $gross_income{$Person} and $income2 < 50_000 }
      You might want to declare some variables to make it strict (that would be extra code). About the only extra code the Perl part has is 2 extra spouse declarations, as hashes aren't symmetric. How does Prolog know that the "spouse" relationship is symmetric?
      However, this is the kicker. What if I want a list of all average taxpayers? Well, I know you have to have a gross income to be an average tax payer, so I issue the following query:
      And in Perl:
      @avg_taxpayers = grep {average_taxpayer} keys %gross_income;
      Now, I know about logic coding, and I'm aware of its merits. No need to convice me. But you've to come with a better example to show you need less code.
Re^6: (why to use logic programming)
by dragonchild (Archbishop) on Feb 14, 2005 at 19:50 UTC
    #define IS_FOREIGNER(x) (!(x->citizen)) #define IS_SPOUSE(x) (x->married) #define INCOME(x) (x->income) ... int is_average( struct Person *person ) { if ( !IS_FOREIGNER( person ) && !IS_SPOUSE( person ) && INCOME( pe +rson ) > 3000 ) { return 1; } else { return 0; } }

    You wrote your code in an OO style. I wrote mine in an imperative style. Why is yours any better than mine? What benefits do I get by writing in an OO style over an imperative style? When would using OO be better than using imperative?

    While you're answering those questions, think about the fact that you're having to explain a completely new way of thinking about problem-solving to me. Think about the fact that you're having to explain concepts that may take months for me to fully comprehend. (And, that's assuming you have grokked those concepts, which you may not have.) Then, you have to answer the question "Why on earth would I ever want to do things that way?!?" And, you'll probably go "Uhh ... uhhh ..." and fumble for an answer.

    Now, think about the fact that Ovid is trying to do the same thing with you, but for a logic-based style of programming.

    For further reading, look over Beating the Averages, specifically the section entitled The Blub Paradox.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      I think I agree with the main thrust of your post, but just to nitpick a little, I don't think you actually wrote "imperative code", at least as far as I understand the term, and perhaps if I'm wrong somebod will correct me. You are actually writing Object Oriented code because you define a set of data then you write methods that operate on this set of data. The fact that the language doesn't have, or you aren't using, any specific syntactical features related to OO code doesn't matter, as far as I know.
        It is a common practice in C to use macros for anything and everything. Take a look at the Perl source and you'll see macros all over the place. Many will be used for data structure access and many will not. The data structures will be accessed through the macros and they'll be accessed directly. The data structure isn't being thought of as a unit. You're working on the data in *person and you are using convenience methods to deal with it. Kinda like why we use constants instead of magic numbers.

        More importantly, there's no way to ask the data structure to perform an action. There's no way to inherit actions or subclass a data structure. There's no way to construct this data structure. It's looks like it's OO only because you saw one small snippet that was written to look very similar to what you wrote.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://430903]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-20 00:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found