4 ms·
Hey, this is good practice! First we can load the csv library, then read the rows of the csv file, and assert those rows as facts using the `car` identifier. (
by hjek 7y ago
Hey, this is good practice!
First we can load the csv library, then read the rows of the csv file, and assert those rows as facts using the `car` identifier. (Doesn't mean `car` like in lisp, obviously, but automobile.)
?- [library(csv)],
csv_read_file('cars.csv',Rows, [functor(car)]),
maplist(assert, Rows).
If we want to find a Ford, then we can enter this query:
?- car('Ford', Model, Year, Colour).
Any capitalised word that's not in quotes is a variable in Prolog, so they can take any value. This will give us the result:
Model = 'F150',
Year = 1999,
Colour = 'Black' ;
Press space, and we get another:
Model = 'Mustang',
Year = 1969,
Colour = 'Blue'.
And there are no more, so it returns to the REPL.
(I should really have discarded the first line, because right now there's a car, whose brand is 'Brand', and so on. Well, well...)
If we just wanted a list of all the results, we could use the findall/3 predicate.
Something that's neat in Prolog is that you can define recursive relations. In SQL it's easy to define a parent/child relation, but what about ancestor/descendant? (Yes, you can use common table expressions, but the syntax is incredibly complicated.)
Also, you don't need to create database schemas and Prolog, and unification feels seamless as opposed to explicitly declaring the JOINs.
But, in my opinion, where Prolog really shines compared to SQL is that there just isn't that whole object-relational impedance mismatch[0].
[0]: https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch https://en.wikipedia.org/wiki/Object-relational_impedance_mi...
Edit: Ok, my turn quiz!! Say we have these bicycles:
Brand, Colour, Year
Mosquito, Blue, 2010
Raleigh, Red, 2005
Suzuki, Red, 1998
In SQL, how would you find the names of any two brands whose bicycles have the same colour? (Don't bother with the whole CSV parsing; just assume it's already a table.)
In Prolog that would be:
bicycle(One_brand, Colour, _),
bicycle(Another_brand, Colour, _),
One_brand \= Another_brand.
Maybe I just have particularly hard time understanding SQL, but I'd have to surf StackOverflow for at very least half an hour to do that in SQL. I wouldn't know where to start.
- new4thaccount 7y agoThanks for working through my example question. I may have to give Prolog another shot at some point!
- krackers 7y ago>how would you find the names of any two brands whose bicycles have the same colour? At first glance I thought it'd just be a group by + having followed by some sort of SELECT to get the first 2 in each group. But apparently doing that top-k in each group is a nightmare in SQL [1]. [1] https://stackoverflow.com/questions/8748986/get-records-with-highest-smallest-whatever-per-group https://stackoverflow.com/questions/8748986/get-records-with...
- yawaramin 7y agoNice quiz :-) My attempt would be: select b1.Brand as brand1, b2.Brand as brand2 from bicycles as b1 inner join bicycles as b2 on (b1.Colour = b2.Colour) where b1.Brand <> b2.Brand
- hjek 7y agoCool! That's actually really close to the Prolog version.
- yawaramin 7y agoTrue that. Only major difference is that I had to explicitly specify how to relate the two brands together in SQL whereas in Prolog it's implicit by using the same variable in two different patterns. I find the idea of a simple Prolog, like a Datalog, very intriguing as a potential simple query engine for apps in mainstream languages–not having to worry about the maps, filters, reduces, flatmaps, and all the other operations we have to do to coax data into the right shapes in line-of-business apps. Unfortunately I just haven't been able to figure out how to do a left outer join (or if that's even the right approach in Prolog :-)
- hjek 7y ago> Unfortunately I just haven't been able to figure out how to do a left outer join (or if that's even the right approach in Prolog :-) That is probably my main issue with SQL: That the names of some of the keywords are very table-ish and not very semantic; like LEFT OUTER JOIN. I mean, if we have some facts, like how old people are, and what they like to eat, then what does it even mean that any of those facts is to the left or on the inside of another? I can't fit that into my brain. But let's take an example. We have these sets of facts (which, if they were in SQL, would be in two different tables): age(alice, 20). age(beatrice, 30). age(charlie, 90). likes(alice, carrots). likes(alice, chips). likes(charlie, crumpets). Then an INNER JOIN would probably be like: age(Name,Age), likes(Name, Something). This can be read as "What is the age of anyone, who like something?" (or more absurdly, "What does anyone, who has an age, like?", depending on what variable we focus on.) I'm probably getting this wrong, but if we wanted LEFT OUTER JOIN it would be more like: age(Name,Age); likes(Name, Something). Which is more like "What's all people's ages, and what does anyone like?" In Prolog, the comma means 'and', and the semicolon means 'or', so in the second query anyone, who has an age but doesn't like anything, will still be included. In this query, that would be Beatrice. That's a bit like a LEFT OUTER JOIN, isn't it? > I find the idea of a simple Prolog, like a Datalog, very intriguing as a potential simple query engine for apps in mainstream languages–not having to worry about the maps, filters, reduces, flatmaps, and all the other operations we have to do to coax data into the right shapes in line-of-business apps. Seen DataScript?[0] I think MiniKanren has also been implemented in most languages. I like how Prolog "forces" a declarative style though. [0]: https://github.com/tonsky/datascript https://github.com/tonsky/datascript