Myself, I would like to see data query/manipulation language as a total functional language, possibly based on the idea of categorical data transformations: https://www.categoricaldata.net/
Also - bit of a rant - if you're creating a new programming language, consider making syntax and semantics separate in the specification. Lots of people get hung up on arguing about language syntax but it's really semantics differences that are important for compatibility. Lot of new languages comes up only to fix syntactic problems with existing languages but create small semantic differences in the process, making automated translation from and to existing languages difficult. I wish we could move to a world where syntax and semantics in programming languages are discussed separately from each other.
I agree. Implementations should accept a stable, machine-friendly format (doesn't matter which; JSON, s-expressions, or even XML would do). If they also accept a human-friendly format, there should be a standard/built-in translation from human format -> machine format (optionally the other way too).
This way, we can always convert random real-world code (scraped from GitHub, or whatever) into a language-agnostic format (yes Python has an `ast` module; that doesn't help a Python linter written in something else, like Go); tools can manipulate this format without having to care about the surface syntax (e.g. linting/doc-gen/static-analysis/versioning/diffing/refactoring/macros/etc.); the output of such tools can always be fed back into the main implementation to compile/run/type-check/syntax-check/etc.
IIRC, Ohm (successor to OMeta) separates syntax from semantics!
Erm, like PromQL?
Edit: also I find the title a bit grandiose since this isn't about Logic Programming in general, but only database querying
I have been looking for examples of how to use a practical implementation of Datalog for years and the closest I've come to is actually miniKanren instead. Could you point me to codebases that productively use Datalog internally?
Would be pretty awesome if we could have logica (or something similar) for dataframes (including pandas), and so could build pipelines of transformations-via-queries on those.
(If there is anything like this already implemented, I'm all ears!).
> English words (...) often capitalized to keep the old-fashioned COBOL spirit of the 70s alive!
I like logic programming a lot but a convention not technologically enforced is a poor reason to argue for a language change. When arguing about SQL limited abstraction capabilities that space would have been better spent talking about CTE limitations, for example.
Also:
> To make things worse, SQL code is rarely tested, because “testing SQL queries” sounds rather esoteric to most engineers, at best
So nonexisting best practices require a language change, apparently. It was also not showcased how this can be done in Logica, beyond the table mocking that could be done with a "with xxx as (values a, b, c) select (query to be tested)" approach in sql.
Look for the section containing the text "As a final example, let us mock the comments table, in a unittest of a query." That demonstrates mocking and is explicitly pointing towards testing. The article is only a high-level intro document.
This really should have demonstration of some of the actual use cases where this shines vs SQL.
Also: SQL-92 has values clause which makes the example provided a little bit silly, you could just use
values (2),(3),(5)
Another example they gave is a 5-line (excluding imported code) mocking code with a comment "compare that to what you would have to do to achieve the same using bare SQL". Okay.. select * from (values (1, 'hello'), (2, 'logic'), (3, 'programming')) as mocktable(user_id, comment); has_descendant(?ancestor, ?descendant) :-
has_child(?ancestor, ?child),
has_descendant(?child, ?descendant).
Here, the assumption is that you have explicit `has_child` facts (expressing vertices in a graph, essentially), and the above rule gives you paths of arbitrary length.In SQL, given a table has_child(parent, child), it is not clear to me how you can get all descendants of a given person, or all ancestors.
Other people talk about recursive extensions to SQL, maybe that provides a way.
The end result is (you hope) a very complex database where the smaller blocks/relationships can be audited and verified quickly, and where parallelization more or less comes for free.
The reality is that Datalog systems end up being massive hairballs of declarations that are hard to unravel for mere humans (well, regular developers) and that query-based solutions are 10x faster to develop for 80% of the application use cases.
The closest parallel is functional-vs-procedural programming (don't flame me); it's a niche solution for niche problems.
Source: former Datalog developer for ERP systems.
Tangentially related, but does anybody know of a program or a library that takes standard SQL queries as input and outputs one or multiple equivalent queries using the SQL dialects of a set of DBMSs? That is, compiles a standard SQL query into a PostgreSQL one, an SQLite one, etc.
So this is going to run into the same issues as any SQL code generator (compare Hibernate for example): you need to know what query it will output. And you need DBA skills to know what that query means in terms of performance. Neither of those steps can be skipped.
Nor is unit testing necessarily helpful when using small n. Issues of poor scaling don't show in tests unless the data is large.
What about optimizations? It seems like it should be possible to construct a SQL query that doesn't hit the pain points (e.g. avoids queries that do not use indexes). Although from my experiences with other ORM frameworks, that probably isn't an easy problem.
Even then though, since it looks like it somewhat aims to replace SQL even in the database-construction step, that might help in this regard, by constructing a more optimal representation of the data (which doesn't seem to be tabular)?
Unit testing I am similarly skeptical about though. The article does mention it being "rather esoteric [sounding] at best", I would actually agree with that expression, haha. I don't think I've ever written or even seen, in my 8 years as a developer, a 100-line SQL query that was not at least partly generated (and hence required testing as a unit, and not just the code around it). I suppose Google operates at a different scale, but still.
Edit: Never mind, the Scryer Prolog github page states it as follows:
Scryer Prolog aims to become to ISO Prolog what GHC is to Haskell: an open source industrial strength production environment that is also a testbed for bleeding edge research in logic and constraint programming, which is itself written in a high-level language.> It supports modules and imports, it can be used from an interactive Python notebook and it even makes testing your queries natural and easy.
I don't see any examples of how to do tests in the announcement. Consider adding some.
* My business clients and I speak SQL together. I don't see them learning a new language. I don't have the authority nor any will to force them to.
* I can spin up a container for testing business rules logic (and often share the results back to the client: here is what the impact of updating rule A is, rows of type W will be affected in this way).
Even though SQL has ceremony/verbosity, I'd rather see the standard be evolved. My clients and I could pick it up more easily.
----
That's great for BigQuery though. You can't spin up a BigQuery docker container anyway, and testing with another schema/project is risky while you have interns around.
I see that one can create predicates (functions) with parameters as a means for code re-use. I could also see that having implications for testability. That's interesting.
I could see how one could build a DSL with Logica to make fairly tricky queries easier. That's interesting.
Has anyone used this? If so could you explain how are SQL functions called? Do they have to specifically exist in Logica or are they just assumed to exist in SQL? (I'm thinking about geographic functions in particular for example. Are window functions also possible in Logica?
Only I wish we had such a language for a more generic streaming / data processing framework, such as materialize [1].
I was very optimistic about that for some time, as the guy behind the technology, Frank McSherry, wrote some datalog tooling as well [2].
It's almost as if people saw OWL 2 DL, didn't believe what it had accomplished, and didn't try to make anything better.
The best way to learn it, in my opinion, is to implement microkanren, which is micro by design for teaching purposes. It is small enough to fit in your head, understand what's unification, and play with it. Then you can jump into other implementations.
If you like clojure, you can use core.logic, although documentation is not abundant.
More prolog-related, The Power of Prolog https://www.metalevel.at/prolog has been praised here several times.
Prolog Programming for Artificial Intelligence by Ivan Bratko.
My recommendation would be to learn the real thing, not an almost, sort-of Prolog that's actually a LISP dialect in disguise.
For Prolog me too wondering if there's a great source. But I have read 'the Reasoned Schemer', it used a simple Scheme-based logical programming language for teaching purposes and it's very educative and entertaining.
Also it's got some small incompatibilities with SWIprolog and I don't know how well amzi works under Wine so it can be frustrating if you're on linux.
The relational model adds constraints, state, and a mechanism for first-class derived relations (updateable views).
And while you can stick anything with a well-defined equality in a relation, including other relations, the point of the relational algebra is to describe structure using relations, thus making it all accessible to relational operators. In a properly normalized database, all structure can be manipulated through a common set of operations.
So you could, e.g. create a relation with a single JSON attribute and call it a day. But now, in addition to the relational operators, you need a whole mess of JSON operators to query it.
Thus, while you could have a sum type, you don't need this because you can put the various summands into separate relations. For instance, the simple case of booleans:
Persons(key id: int, name: str, is_tall: bool)
... noramlizes to ...
Persons(key id: int, name: str)
TallPersons(key id: int)
Or for an Either: Persons(key id: int, name: str, zing: either<int, str>)
... noramlizes to ...
Persons(key id: int, name: str)
LeftPersons(key id: int, zing: int)
RightPersons(key id: int, zing: str)
AssertEmpty: LeftPersons{key} & RightPersons{key}
What you really want your database to do is to let you enter that first "Persons" table with the sum type. That should logically be a derived table that is backed by the normalized tables.Then, you'd get the simplicity of entering Persons.insert(key=5, name='bob', zing=Left(5)), but that's simply an updateable view. It will really update the base tables Persons / LeftPersons with simple atomic values.
I can't find any mention of recursion on the original blog post or the GitHub page. Without recursion it isn't Datalog.
There is a syntax debate I respect. While I prefer austere syntax, deeper thinkers like Bill Joy note that programmer productivity increases with more information on screen at once. Syntax that improves both code density and clarity is a good thing. I love Haskell and Ruby in actual use, even if I want to prefer Lisp without parentheses (an easy preprocessor if one thinks it through).
I cannot respect perpetuating C syntax just to attract users who would otherwise be challenged (that Apollo 13 astronaut who "never trained in the LEM"). Rob Pike once gave the only justification I can understand: Code used to need to survive communicating through channels that mangled whitespace.
That is no longer the case, and modern editors all support syntax highlighting. (We've reached the point where one should develop an editor language server in parallel with any new language.)
If your editor can figure out your language's grammar, and then you can with the editor's help, then one achieves greater code density and clarity at once. Some people do love terminals, but most people use graphical user interfaces. Why is language design stuck in terminal pre-history? There is no excuse in 2021 for lots of stray punctuation that's just ground glass in programmers' eyes.
I strongly prefer verbose type systems, in particular, some lightweight type inference is good as long as it's not full fledged HM type inference (like Haskell, Rust etc). The problem with HM type inference is although it's extremely powerful and makes the code look cleaner, it hides important data from programmer, which ultimately causes 2 bugs:
* variables being inferred to have types slightly different than ehat programmer expects. E.g. I expected foo to be A(B(C)) -> D(C) turns out it's actually A(B(X)) -> D(C) which also type checks.
* Errors can be harder to read.
This is objectively bullshit.
What SQL database engine doesn't provide views, stored procedures and/or user-defined function support?
Failure to construct higher-order abstractions in SQL is a failure of the engineer to understand the problem domain, not a failure of the tool.
SQL is capable of operating at any level of abstraction you wish for it to. It is all engineering from there.