Artificial Intelligence Coding - Perl or Lisp? 16
blackcoot asks: "I'm currently suffering through an undergraduate class in AI where it appears that the first commandment of implementation is 'Thou shalt use Lisp of suffer the wrath of the TA'. I've been hacking away at Lisp for the past week now, and I've come to two conclusions: I hate Lisp; and Perl seems to have all the closure features that made Lisp so good in the past for AI [i.e. judicious use of
eval(...)
and a little creativity can replace Lisp's (lambda ...)
]. I'm looking to learn as much as possible from this class and hopefully not die implementing the projects in the process, so I'm hoping some of you out there can either point me in the direction of a decent Lisp manual or help me formulate arguments in favor of letting students use Perl as the implementation language." I can surely emphasize with blackcoot's troubles with Lisp, but can Perl emulate the features of Lisp that make Lisp good for AI? Might Perl have some advantages over Lisp when it comes to writing AI code?
"I think my major source of frustration is that the all the documentation that I've found on Lisp out and out sucks and the recommended text for the course ANSI Common Lisp by Paul Graham is pretty useless except for the appendix which has a list of usage for all the macros and functions in ANSI Common Lisp."
Those of you interested in comparisions of Lisp with other languages might be also interested in the recent comparison of Lisp and Java, as well.
Eval??? (Score:1)
I don't know what you're doing with eval, but the Perl equivalent of lambda is sub.
Try this:
$foo = sub ($) { 1+shift };
print &$foo(5)
equivalent of lambda? (Score:3, Interesting)
Not sure I completely understand the equivalence here. What perl code would be equivalent to the following Scheme code?
(define (foo n)(lambda (m) (+ m n)))
(define bar (foo 1))
(define baz (foo 2))
(display (bar 5))
(display (baz 5))
Re:equivalent of lambda? (Score:4, Informative)
(define (foo n)
(lambda (m) (+ m n)))
(define bar (foo 1))
(define baz (foo 2))
(display (bar 5))
(display (baz 5))
OK, so just remember that I'm arguing the Lisp side of this debate, but since I *do* know my Perl:
sub foo {
my $n = shift;
sub {
my $m = shift;
$m + $n;
}
}
my $bar = foo(1);
my $baz = foo(2);
print &$bar(5);
print &$baz(5);
Ugly, isn't it? And when you start trying to translate real code instead of toy code it just gets uglier and uglier and more and more obscure...
Re:equivalent of lambda? (Score:1)
def foo(n):
return lambda m, N=n: m+N
bar = foo(1)
baz = foo(2)
print bar(5)
print baz(5)
You might also look at an article on developerWorks about functional programming in Python. [ibm.com]
Re:equivalent of lambda? (Score:1)
Alot of languages have anonymous functions and the ability to read, at definition time, from the enclosing environment. Can Perl also modify bindings from this environment as well as share bindings across multiple functions? I am not being clear, I think, so a code segment might be clearer. What is the Perl equivalent of the following Scheme code?
;;; Nobody dig on the code, this is a contrived example, and
;;; yes, I know there might be "better" ways to do this.
(define (linked-counters value)
(cons (lambda (increment) (set! value (+ value increment)) value)
(lambda (decrement) (set! value (- value decrement)) value)))
(define counters (linked-counters 3))
(define increment-counter (car counters))
(define decrement-counter (cdr counters))
(increment-counter 4)
(decrement-counter 10)
In Scheme the result is '7' then '-3'.
And of course, Scheme has the Real Programmers' favorite function 'call-with-current-continuation'. Quiche eaters will never understand it; it changes __everything__.
There is more than one "Lisp" (Score:3, Informative)
Perl datastructures (arrays and hashes) also aren't very well suited to implementing lists, which are likely to turn up in your tasks. Of course you r can *do* it, but it's likely to be more ugly in than in a proper Lisp.
But you before you despair in a maze of twisty little parens, you should realise that there is more than one language in the Lisp family. Common Lisp and Scheme do have lots of parens, but take a look at Dylan [gwydiondylan.org]. It's a true member of the Lisp family, but looks and feels like a conventional langauge such as C or Pascal.
The link above is to an Open Source command-line compiler for Dylan which workes primarily on Un*x but also has ports to Mac and Windows.
If you happen to be using Windows then also check out Functional Developer [functionalobjects.com], a compiler with a nice IDE and debugger and so forth. It's commercial but the basic edition (whcih is all you'll need) is free.
Dylan is quick to develop in and the programs run fast. A team using Dylan got second place in the recent ICFP [inria.fr] Programming Contest.
Re:There is more than one "Lisp" (Score:2)
Perl datastructures (arrays and hashes) also aren't very well suited to implementing lists, which are likely to turn up in your tasks. Of course you r can *do* it, but it's likely to be more ugly in than in a proper Lisp.
These are mantras that I've heard regularly from Lisp and functional language users, but I've yet to see them thoroughly backed up.
Perl coders use functions *all* the time. Even OO method calls are implemented as simple functions. If you need named parameters, use a hash or hashref. There are even modules [cpan.org] that validate [cpan.org] parameters [cpan.org]
so you can have a call signature.
As far as arrays not being lists, I don't get this one either. In what way are Perl arrays not lists? With functions like pop, push, shift and unshift, and array is treatable exactly as a list. Now, I don't know if lisp does lazy evaluation, if so that's something Perl doesn't do, and would be a very valid point against it. But you didn't mention that...
Seriously, I'm not trying to flame. I'm geniunely curious about these points.
Matt.
Re:There is more than one "Lisp" (Score:2)
Why do you imagine that I'm not a Perl "coder"? I unfortunately spend *way* more time programming in Perl than in Lisp because Perl has somehow become "cool" while much better languages have irrational prejudices against them.
If you need named parameters, use a hash or hashref.
At the cost of a bit more syntax, and a *whole* lot more inefficiency! Not that the standard "my ($a, $b, $c) = @_" is the model of efficiency!
These are the sorts of things that you can get away with when the atoms of your computation are calls out to Unix programs or pipelines. It just doesn't cut it when you're doing some AI-ish routine that requires millions of calls to functions.
There are even modules [cpan.org] that validate [cpan.org] parameters [cpan.org]
so you can have a call signature.
Yet *more* layers of inefficiency, just to buy you what real languages have built in from the start, usually with *no* runtime overhead!
As far as arrays not being lists, I don't get this one either. In what way are Perl arrays not lists? With functions like pop, push, shift and unshift, and array is treatable exactly as a list.
The point you're missing is that linear lists are just one special case of what Lisp programs build from cons cells. Lisp "lists" can share tails with each other, can be circular, can actually be trees or any other shape, and can have arbitrary stuff efficiently inserted or deleted in the middle.
You just can't fake this with a Perl array. The best you can do is use one Perl array for each node in the List.
ChatBot (Score:1, Interesting)
(the original was in LISP if I'm not mistaken).
Another Alternative to Perl is Tcl (Score:1)
Books on Lisp (Score:2)
Have you looked at Common Lisp: The Language [n-a-n-o.com] by Guy Steele?
BTW, yes, it's that Guy Steele.
couldn't have picked a worse forum to ask in (Score:2, Insightful)
This is a genuine question from an actual student with no choice as to what language will be used for homework. Not just lisp vs. non-lisp, but no choice as to which dialect to use. Probably no choice as to which implementation.
Slashdot articles that mention more than one programming language are forums for language wars. You don't come here for actual, help, silly!
Why don't you pop on over to comp.lang.lisp and ask about Common Lisp reference texts other than the one you're dissatisfied with. They might point you to one that would be more to your liking.
Now please pardon me while I go flame at those who denigrate my favorite language or languages similar to it. :-)
other references (Score:2)
Well, if Graham isn't your cup of tea, you should definitely take a look at Norvig's Paradigms of Artificial Intelligence Programming (which is actually of interest to a much wider audience than just AI people, but I digress). As someone else said, Steele's book Common Lisp: the Language is good, thought it predates the ANSI standard, hence you need to be a little careful. The standard itself (or more likely, the Hyperspec, which you can find online at various places; check for example Xanalys [xanalys.com]; there should be a copy around there somewhere. You can certainly download it, if not independently, as part of their personal edition of Lispworks) is very readable and informative. For a starting CLOS reference, try Sonya Keene's book Object-Oriented Programming in Common Lisp.
Of those, I particularly recommend Norvig, and recommend that you get a copy of the Hyperspec, which you will quickly find much more useful than the back of Graham's book. You might also want to describe exactly what Lisp system you are using, as this may possibly help us give further advice.
While I would personally rather implement almost anything in Common Lisp than Perl (the primary exceptions being when Perl's CPAN advantage comes into play), I certainly sympathize with your plight; it's hard to imagine why they oughtn't let you implement your projects however you like.
Give lisp a better shot (Score:2)
Lisp is a different language from most languages currently in vogue. To be successful, you'll need to think somewhat differently. That's why it's so hard the first week, but it will get easier. The stretching your brain goes through will make you a more versatile and better programmer in the end.
To make the learning curve easier, make sure you're using a good environment to work with your lisp. Traditionally, lisps work best with an environment which understands lisp, can allow you to evaluate s-expressions at a keystroke, and work with the incremental compilation that makes lisp a joy to work with. With an environment which supports paren-matching and auto-indenting, the mass of parentheses is no longer a problem.
There are a number of good lisp environments... most commercial lisps come with one, I believe. Emacs is also good (unsurprisingly). Ask your TA what they prefer... if they don't have a preference, ask the prof. Unlike perl or C, and like Smalltalk (I've heard), the development environment is an integral part of making Lisp what it is.
So, please, give it a try. You'll be better for it.
Stop Complaining! (Score:3, Informative)
I simply cannot emphasise enough how valuable it is to learn as many programming languages as possible. Even if you don't really like it at first, a language can grow on you in ways you would have never imagined. No language is perfect, so knowing a selection of different languages will give you the opportunity to choose a tool that is appropriate to the job in hand. If the only tool you have is a hammer, then every problem you come across starts to look like a nail.
By keeping your horizons broad, most especially by learning languages that might seem strange, counter-intuitive or even downright annoying at first, I can assure you othat you will become a much, much better programmer in the long run. The ways in which languages differ can often give you an insight into the ways that different programmers might solve the same problem.
FWIW, the presence of closures and eval are not the only things that make Lisp distinctive from other languages. The one truly unique (not to mention incredibly powerful) feature of Lisp is macros. You will not be able to find these in Perl. Also, in Perl the standard way to solve problems is with an iterative, procedural style, where Lisp more often employs recursion and an applicative programming style, both of which are techniques well worth the effort to learn about.
Whether Lisp is better than Perl for AI is debatable. I'd argue in favour of Lisp for the following reasons: one is the fact that Lisp is extremely good at knowledge representation (and the subsequent manipulation of that knowledge), but more important is Lisp's ability to generate code with macros, effectively meaning that you can write programs to write other programs. It's also probably worth noting that Lisp is quite a lot faster than Perl, given a decent enough compiler. See The Programming Language Shootout [bagley.org] if you don't believe me. Lisp is also a very mature language, with an ANSI standard, so unlike Perl you can be certain that it won't be pulling any carpets out from underneath your feet any time soon.
If I haven't done a enough good job of convincing you that learning Lisp is worthwhile (and I probably haven't) then try checking out Paul Graham's Beating the Averages [paulgraham.com]. Also, be sure to check out Richard Gabriel's Good News, Bad News and How to Win Big [mit.edu]. And have a read of Paradigms of Artificial Intelligence Programming by Peter Norvig [norvig.com] for some more specific examples of Lisp as an AI programming language. Particularly relevant might be the section in the preface entitled Why Lisp? [norvig.com].
And when you're done with Lisp, I'd recommend a look at Ocaml [ocaml.org], SML [bell-labs.com], Ruby [ruby-lang.org] and Smalltalk [smalltalk.org] (particularly the delightful Squeak [squeak.org])!