Lisp in Prolog in zero lines
stud4.tuwien.ac.at
stud4.tuwien.ac.at
The "in zero lines" part doesn't really make sense, because most language runtimes use existing functionality in the language of implementation.
Also, the "3842534 Lips" bit on the timer lines is a typical Prolog measurement, 'logical inferences per second'. ("Infinite Lips" is pretty silly, though.)
Erlang and Oz are both from Sweden, and Sicstus Prolog (of the Swedish Institute of Computer Science) is one of the most prominent Prolog implementations. Perhaps Prolog is/was more popular there than elsewhere?
Prolog is a fun language, on it's own, but one feels like his arms have been cut off and his legs made 100 times more powerful when using prolog; it empowers you in some aspects, but completely disables you in others. So, many people opt to get it in a form where it's embedded in Lisp, to augment its shortcomings and exploit its powers.
Prolog can do neat tricks (difference lists!) with infinite data structures by passing around unbound variables, and then "retroactively" binding them, perhaps partially, further in the execution. It's conceptually different from lazy evaluation (more like dataflow variables), but has many similar applications. I wouldn't be surprised if it does handle closures automatically during unification of the code tree, though I can't check at the moment.
Prolog works by filling in all the blanks in a way that makes sense as a whole, but in this case it happens that the check if something could have been passed in as an argument can be used to set the argument to it, if valid. This probably sounds like weird quantum physics stuff, but Prolog is capable of testing whether the variables in the goal being tested are bound, explicitly binding and revoking them, collecting the list of possible valid bindings, etc.
Prolog is also homoiconic, has macros, and is built out of atoms and arbitrarily nestable lists. (Its design is very strongly tilted towards pattern matching and search, though, so it's less of a general-purpose language.)
Parsing Prolog is actually pretty easy (the syntax is almost as simple as Lisp's!), but IIRC the Prolog-in-Lisps I've seen in PAIP and On Lisp just use native Lisp sexps. While the Prolog-y syntax strikes me as a bit weird in Erlang, it actually makes a lot of sense for Prolog.
2.) Now point me to the Prolog interpreter in Lisp in 1 line.
3.) Now for the rant: Looks like we slowly recognise how silly it was to hop on the oop/imperative programming track. All we got from it: everyone and his mom programming, their code soo explicit it destroys the entropy balance of the universe, mankinds software library mostly non reusable trash.
...and the sunscreen.
OOP and FP are very similar. You can bet that if the average Enterprise Java Programmer used Haskell instead of Java, the code would be just as confusing and unmaintainable. The problem is not programming paradigms, but bad programmers.
(Programming is difficult to teach, learn, and practice, but is also in high demand. This leads to bad programs. OOP has nothing to do with it.)
I certainly agree that immutable data is better than mutable data, but that again has nothing to do with FP or OOP. I can mutate data in Lisp, and I can have fully-immutable instances in Java (not my choice, btw, but definitely possible). It comes down to recognizing the value of immutability, which is the programmer's job.
(I am glad to say that I have not yet written "class Foo does Monad, Functor {}" ;)
(I'm assuming it's not in a language like OCaml or Oz that can comfortably fit both styles.)
Personally, I rate the perversity of bad coders as being well above Haskell's ability to prevent perversities, but the fight would be truly epic and produce months worth of tdWTF fodder. I don't know which would be worse: Them discovering unsafePerformIO, or them not.
run("
(defun append (x y)
(if x
(cons (car x) (append (cdr x) y))
y))
(append '(a b) '(3 4 5))", V).
works, because Prolog can unify the former with its result ("does the Lisp expression provided have a result we can determine? Yes, and it's [a, b, 3, 4, 5]"). If you try to unify with the opposite variable unbound ("Is there a valid Lisp expression that results in [a, b, 3, 4, 5]?"), it starts generating a depth-first traversal of every possible valid Lisp expression according to the grammar * (with logic variables; templated, sort of), and could e-ven-tu-a-lly find the append expression. For me, on SWI-Prolog, it just runs out of local stack. If the program had been designed with that use in mind, there would be changes to the design to greatly reduce the search space. Regardless, "Generate every possible syntactically valid program and test each of them until one makes all my test cases pass" is probably a pretty slow way to write code. :)I found Prolog really confusing when I thought about it as "going backwards". Really, it tries to determine if a completely instantiated version of the expression you give it exists (according to the facts and rules you've provided), like trying to fill in a sudoku puzzle. If there isn't a valid solution, it says "no.", otherwise it searches (depth-first) and pauses to present any solutions it finds along the way. "Fill in the missing pieces, backtracking to give multiple solutions" is a fundamentally different style of evaluation than "apply this function to these arguments, return the result", and ideas of forwards/backwards doesn't directly apply. (Unsurprisingly, doing I/O in Prolog gets a bit weird...)
In some cases, this means rules have several uses. member(Item, List) can be used both to get each value from a list one at a time ("member(X, [1, 2, 3]" -> 1, 2, 3) and to get all generic lists that contain a value ("member(3, L) --> [3|_G242], [_G241, _3|_G245], [_G241, _G244, 3|_G248], ..."; those are gensyms). This doesn't always work (e.g. add(3, 5, X) succeeds with X=8, add(3, X, 8) needs extra declarations), in part because Prolog doesn't know to try integers unless you tell it (in the above case, "between(X, 1, inf)".)
* Based on a quick glance at the code and my understanding of Prolog, thus far.
Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp
Prolog follow-up
Any sufficiently complicated LISP program is going to contain a slow implementation of half of Prolog. """