6 ms·
Prolog is extremely different than other programming languages and as a result, learning it and writing a few small programs is very mind expanding. It really
by gnarbarian 10y ago
Prolog is extremely different than other programming languages and as a result, learning it and writing a few small programs is very mind expanding.
It really drives home how different paradigms are suited to different problems. Prolog is suited toward problems like Einsteins riddle
https://udel.edu/~os/riddle.html https://udel.edu/~os/riddle.html
- jamesbvaughan 10y agoThe class I was taking kind of blew my mind when I saw how you can solve some problems in such cool ways with Prolog, but I would certainly admit that this server isn't exactly the kind of use it's best suited for.
- xapata 10y agoPython's set class and comprehension syntax can get you much of the declarative power of Prolog.
- justinhj 10y agothat's a tiny subset of what Prolog can do
- siddboots 10y agoHow so? I mean, there are logic libraries available for python to be sure. But the "set class and comprehension syntax" are two features only tangentially related to logic programming. Using them alone doesn't get you inference, or even unification.
- xapata 10y agoInference is straightforward using dictionaries, membership-testing, and set methods, like subset, superset, disjoint, union, intersection, and difference. Python can't do a conditional assignment as nicely as Prolog's unification, but you can get similar behavior via the application of predicates in comprehensions and using set methods. I'm not saying Python is equivalent, but simply that you can get some of Prolog's style in Python. Erlang's pattern matching and concept of bound vs unbound variables is a bit closer to Prolog's unification. Here's some Python implementations for examples shown in my first Google result for "prolog examples" (http://www.cs.toronto.edu/~sheila/384/w11/simple-prolog-examples.html http://www.cs.toronto.edu/~sheila/384/w11/simple-prolog-exam...) 1. Here are some simple clauses. >>> likes = {'mary': {'food', 'wine'}, ... 'john': {'wine', 'mary'}} >>> 'food' in likes['mary'] True >>> 'wine' in likes['john'] True >>> 'food' in likes['john'] False >>> # John likes anything that Mary likes >>> likes['john'] |= likes['mary'] >>> # John likes anyone who likes wine >>> likes['john'] |= {name for name, objs likes.items() if 'wine' in objs} >>> # John likes anyone who likes themselves >>> likes['john'] |= {name for name, objs in likes.items() if name in objs} 2. Slightly more complicated family tree. >>> male = {'james1', 'charles1', 'charles2', 'james2', 'george1'} >>> female = {'catherine', 'elizabeth', 'sophia'} >>> parents = {'charles1': 'james1', ... 'elizabeth': 'james1', ... 'charles2': 'charles1', ... 'catherine': 'charles1', ... 'james2': 'charles1', ... 'sophia': 'elizabeth', ... 'george1': 'sophia'} >>> # Was George I the parent of Charles I? >>> parents['charles1'] == 'george1' False >>> # Who was Charles I's parent? >>> parents['charles1'] 'james1' >>> # Who were the children of Charles I? >>> {child for child, parent in parents.items() if parent == 'charles1'} {'charles2', 'james2', 'catherine'} 3. Recursion: Towers of Hanoi >>> def move_one(x, y): ... print('Move top disk from {0} to {1}'.format(x, y)) ... return True ... >>> def move(n, x, y, z): ... if n == 1: ... return move_one(x, y) ... m = n - 1 ... move(m, x, z, y) ... move_one(x, y) ... return move(m, z, y, x) ... >>> move(3, 'left', 'right', 'center') Move top disk from left to right Move top disk from left to center Move top disk from right to center Move top disk from left to right Move top disk from center to left Move top disk from center to right Move top disk from left to right True 4. An example using lists: This last one is a bit silly in Python as all the tools shown are built-ins.
- siddboots 10y agoI appreciate you taking the time. Your approach shows the first steps towards building an inference engine in Python, but these are all very trivial examples. The difference between this and a real logic language will become apparent as the database of facts and rules becomes more complicated. In order to follow this through, you would need to separate all of search code (i.e. the comprehensions) from the declaration of facts and rules. If you were successful in doing so, you will have made a basic logical inference engine in Python. Consider one of the queries described in the family tree example: "M is the mother of X if she is a parent of X and is female" In Prolog this might look like: mother(X, M) :- parent(X, M), female(M). Having built that rule, I can ask 1) Who is the mother of sophia? : mother(sophia, X). 2) Who is sophia the mother of? : mother(X, sophia). 3) Which mothers have male children? : mother(M, X), male(M). The question is, how would you define the `mother` relation using comprehensions in a way that is agnostic to the specific questions that will be asked? You would inevitably need to write different loop for each variant of the question. The trick is to write an engine that, given a query, automatically generates the comprehensions required to find the answers. It isn't an easy problem at all. To make this even clearer, consider your claim that the tools in part 4 are trivial in python, because they are all built-ins. But this is not true at all! Python's built-ins are one-way functions, rather than relations. In python I can ask "what is the sum of the elements in this list?" but I can't as easily ask "what is a list with 30 unique integer elements that sum to 100" To do this in python you would need to put some thought in to how you would generate lists using nested loops so that all of the properties were satisfied. In Prolog you just list the search criteria and it does the work for you: size(L, 30), unique(L), sum(L, 100). Edit: By the way, check out pyDatalog if you are interested in a fully featured inference engine built in python: https://sites.google.com/site/pydatalog/ https://sites.google.com/site/pydatalog/
- xapata 10y agoProlog relaxes the requirement to think linearly, bottom-up. If you write all the facts and predicates bottom-up it's easy in Python. Dictionaries, sets, and comprehensions take care of everything. As you say, it's trivial. If you want to write top-down, defining what a mother is before defining who are parents and who are female, then you'll need to write functions and it gets trickier in Python. The sticking point is when to transition from functions to dict/set -- what's a predicate and what's a fact. We could get fancy with decorators to create some funky predicate class, but let's stay away from metaprogramming for the moment. I agree that Python (without getting fancy) requires the programmer to think through a bit more of the inferential logic than Prolog would under some circumstances. How often do those circumstances arise in practical problems? I'm not sure. However, I've got to accept the challenge: "What is a list with 30 unique integer elements that sum to 100?" First, there is no list with 30 unique positive integers that sum to 100. >>> sum(range(30)) 435 Allowing negatives would create an infinity of possible solutions. So, I'm going to rephrase the problem: Generate a list of N unique positive integers that sum to M. >>> from itertools import combinations >>> m = 30 >>> n = 5 >>> combos = (c for c in combinations(range(m), n) if sum(c) == m) >>> next(combos) (0, 1, 2, 3, 24)
- doublec 10y agoYou might be surprised! SWI Prolog has libraries for web applications (http://www.pathwayslms.com/swipltuts/html/index.html http://www.pathwayslms.com/swipltuts/html/index.html) and other modern application development toolkits. Their online IDE (http://swish.swi-prolog.org/ http://swish.swi-prolog.org/) is written in Prolog.
- rtpg 10y agoA very interesting aspect of Prolog is how its primary primitive is backtracking search. This is orders of magnitude more complex than C-language style primary primitives which closely match single machine instructions. Or even slightly more complex models in lazy languages like Haskell. It's strange that you can build a language almost purely off of graph search yet have it be generally useful. Makes you wonder what other techniques spawn their own paradigm.
- Allan_Smithee 10y agoThere's at least one language (Refal: there may be more!) based on Markov algorithms. Another language (XL: as far as I know this is the only one of its breed thus far) works at its core on parse tree substitution. Yet another (CHR) does a weird generalization of term re-writing to provide a toolkit for making constraint languages. (Yes, a language to make languages.) There's a reason I've become a programming language whore.
- vram22 10y ago>(Yes, a language to make languages.) Are there any other languages that are mainly designed with the goal of making it easier to make other general-purpose languages (as opposed to languages for DSLs or parser generation etc.)? I know that generally many languages are written in C or compile to C, and that Lisp can also be used to make other languages or sub-languages. But asking about languages (mostly) dedicated for that purpose - creation of new general-purpose programming languages.