This is almost exactly like the descriptions I get from my team leader for getting results out of a database. He doesn't think in sets for SQL.
I love Prolog syntax. I do think there is room for improvement, but the language is also extremely flexible, and it is very easy to roll your own syntax. Funny enough, so far my many experiments with alternative syntax have mainly had the effect of convincing me of the elegance and power of standard Prolog syntax.
While there is no particular reason the '.' should be used to terminate statements (except the resonance with many natural languages in this regard), I think some sort of terminator is necessary to keep the syntax as flexible as possible. Like Lisp, Prolog syntax is isomorphic to its AST. Currently my main gripe with Prolog syntax is that it represents conjunction and delimitation of predicate arguments and list items with the same operator, `(,)/2`. However, that can be fixed in two lines:
:- op(1000, xfy, user:(&)).
A & B :- A, B.
But I'm not sure it really needs "fixing"...Regarding, "batching up a bunch of attributes into one conceptual 'thing'": SWI-Prolog has implemented a special data structure it calls "dicts"[dicts] for this purpose, but I am not very fond of it (and there's a fair amount of concern over the way this implementation breaks compatibility with ISO standards). More traditional solutions are to use lists of "pairs"[pairs], option lists[option], or, for larger data structures and when performance and lookup time is an issue, association lists[assoc] or records[records]. Using the first of these techniques looks like this:
my_foo(a, [bar-Bar, baz-Baz]) :-
Bar = something,
Baz = something_else.
get_attr(Pairs, Key-Value) :-
member(Key-Value, Pairs).
set_attr(Pairs, Key-Value, NewPairs) :-
( select(Key-_, Pairs, Key-Value, NewPairs), !
; NewPairs = [Key-Value|Pairs]
).
?- my_foo(a, As), get_attr(As, baz-X), writeln(X), set_attr(As, boz-another_thing, Bs), writeln(Bs).
something_else
[boz-another_thing,bar-something,baz-something_else]
As = [bar-something, baz-something_else],
X = something_else,
Bs = [boz-another_thing, bar-something, baz-something_else].
It might be the case that Prolog's flexible syntax leaves it spoiled for choices here... That being said, it would be straightforward to implement syntax similar to your description, which evaluates and replace attribute accessors in place, using `term_expansion/2` and `goal_expansion/2`. Then you could use `As.baz` in place of the value itself (I've done so before, and this is what the SWI-Prolog's dict expansion does). Even easier, you could use Michael Hendricks' func package[func] to make a function for this purpose. But I've increasingly come to think of Prolog's explicit evaluation as a unique strength rather than a problem to be solved.[dicts]: http://www.swi-prolog.org/pldoc/man?section=dicts
[pairs]: http://www.swi-prolog.org/pldoc/man?section=pairs
[option]: http://www.swi-prolog.org/pldoc/man?section=option
[records]: http://www.swi-prolog.org/pldoc/man?section=record
Thanks for the links! These look extremely helpful!
I think Prolog rules can replace a lot of spaghetti code: stuff like "Usually do this, but then other times do this, unless this other thing is true. If there's a parse error, then do xyz and keep going." In ordinary procedural code, the exception cases can dominate the body of a function and may need to be deeply nested, but in Prolog, it's possible to cordon them off or express them at the top level.
I suspect it might be most useful as a DSL you can embed inside of other languages, though I haven't seen a good implementation of that. (The clojure core.logic library mentioned elsewhere looks really promising.)
I think it may also be useful for domain experts to specify simple rules that capture an aspect of their expertise. If you restrict the domain down enough, and work to figure out what predicates are needed, prolog rules can become easy enough to read that you don't need to know much programming to use them. But the devil seems to be in the details of connecting the core logic into a bigger system that actually does something.
For example, the answer for hooking prolog up to a SQL database is "Look at the ODBC library!", which is not a very satisfactory answer. I think you could build a really beautiful ORM system in Prolog, but nobody's done it yet. (Maybe ORM isn't the right phrase, but a clean way of relating prolog queries to database queries and vice versa.)
The syntax is wonderfully simple, but also has almost no sugar for common idioms. The predicate notation makes it somewhat harder to batch up a bunch of attributes into one conceptual "thing" than in other languages. That means you need to keep positional arguments in your head a lot more. I think aping the class constructor and attribute notation of other languages would be helpful like `my_foo(foo, bar:attr, baz:attr) :- [...].` Then you could reference that either as a constructor (`my_foo(a,b,c)` would state that `a.bar=b` and `a.baz=c`) or to generate goals, like `my_foo(foo), other_predicate(foo.bar)`. Prolog is so old that choices like "make '.' the end of a statement" made sense at the time, but haven't stood the test of history.
(Disclaimer: Many of my criticisms may have perfectly valid solutions in prolog. I'm still learning it.)