Ask HN: How would a goal-oriented programming language look like?
Reading this article and discussion: There Are Three Programming Paradigms (2013) https://news.ycombinator.com/item?id=13612587
Imagine you could design a general purpose goal-oriented programming language. I was wondering how would such a language look like.
Actually, I've been having much spare time lately, so I'd like to actively research this topic.
25 comments
[ 3.1 ms ] story [ 70.8 ms ] threadLogic-programming style control flow can be implemented on top of these two primitives.
It specifically mentions that the kind of "missing paradigm" looked for is not one of the declarative ones we currently have (SQL, Prolog, etc) because those fall into the Evaluate + Consequent combo.
So, he gives 3 paradigms:
FunctionalProgramming -> Evaluate + Mechanism (list of instructions)
ImperativeProgramming -> Execute + Mechanism
LogicProgramming/ConstraintProgramming -> Evaluate + Consequent (i.e. towards a consequent (result) based on constraints) [this is where declarative falls).
So, the "goals oriented" language he defines as the missing: Execute + Consequent pair.
Designing a language in the abstract usually doesn't work, it is better to start with use cases that demonstrate how the new approach helps expressing nicely what was cumbersome in previous languages.
https://docs.racket-lang.org/racklog/index.html
https://docs.racket-lang.org/parenlog/index.html
https://docs.racket-lang.org/datalog/index.html
The more papers I read the more lost I became trying to make sense of the different approaches to goal-oriented / relational / logic programming. This retrospective paper by Robert Kowalski gave me an historical framework to make sense of it all: https://www.doc.ic.ac.uk/~rak/papers/History.pdf
One of the key insights I gleaned from that paper is the difference between bottom-up and top-down strategies. All logic / relational / goal oriented paradigms exhibit a characteristic top-down or bottom-up quality, and this classification can then be used to understand the essence of goal-oriented programming.
The following is my interpretation of the historical information from that paper:
During the 1980s a burgeoning Datalog community, with roots in the database field, assimilated the existing deductive database community which had roots in AI. The database perspective focuses on finite models that are computable bottom-up. However a naive bottom-up implementation, deducing forwards from facts using rules, ignores the query until it derives it "as though by accident." To make generated models relevant to the query, Datalog uses transformations such as "Magic Sets" to incorporate the query into the rules.
An early deductive database (AI) strategy was Hyper-resolution, which is essentially also bottom-up, and it suffers from the same problem of generating new derivations blindly until one matches the query "by accident". Another strategy known as "set of support" restricted the inputs (axioms) so as to keep the derivations relevant to the query. However, according to Kowalski, set of support only approximates top-down reasoning, and a better approximation is linear resolution.
"Linear resolution addresses the problem of relevance by focusing on a top clause C0, which could represent an initial goal."
A problem which stood in the way of implementing this top-down strategy was the fact that given "n" clauses there are "n!" ways to compute the conjunction.
"The obvious solution was simply to resolve upon the literals in the clauses Ci in a single order. This order can be determined statically, by ordering the literals in the input clauses, and imposing the same order on the resolvents. Or it could be determined dynamically, as in selected linear (SL) resolution."
Thus, you see, it was the invention of SL, soon extended to SLD resolution (the D stands for "definite clause") which enabled top-down logic programming such as Prolog to be computationally tractable.
This top-down versus bottom-up distinction is what separates something like, e.g. language integrated query (LINQ) from logic programming: despite the similarity as a declarative form, a LINQ statement is computed bottom-up because datasets are generated and transformed in a forwards (i.e. not contingent) manner. In contrast a Prolog-style logic query (such as the Castor C++ library) is computed top-down: the query consists of an AND-OR tree of goals and subgoals which is visited top-down.
I'm familiar with Prolog and its implementation, but definitely didn't know all of that.