Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Most programming language are Turing complete and if so they're also general purpose by definition. You can use them to build anything.

How long do you think it would take to write a web server in Rule 110?

https://en.m.wikipedia.org/wiki/Rule_110

Turing completeness is an interesting theoretical concept, but it is wholly unsuitable and largely irrelevant when discussing the usefulness of programming languages.



What is "usefulness" then? It's clear that different programming languages are more suitable for different use cases, for example one wouldn't normally script a browser in Lua or use Javascript to write a driver for a hardware device.

That said, if it's about use cases, Prolog is an excellent language for web development and capable of replacing most of the usual mixed OOP and relational stack. For example, the SWI-Prolog website runs on SWI-Prolog's own http libraries.

Quoting from https://www.swi-prolog.org/dogfood.html:

This page presents a brief history of hosting and developing http://www.swi-prolog.org. The website runs SWI-Prolog and is basically `PlDoc, the SWI-Prolog source documentation system on steroids'. This site replaced a classic Apache server built from static documentation pages, a Twiki-based wiki and Bugzilla. The site was re-implemented as a SWI-Prolog-based HTTP server that extends PlDoc for the following reasons:

1. PlDoc unites the core reference manual with the package documentation and documentation extracted from all loaded sources in a coherent interface. In addition, it provides search, dynamically generated hyperlinks between the various pieces of documentation, and display of the source code. This is far better than the fragmented and not properly interlinked static documentation of the old site.

2. SWI-Prolog comes with extensive libraries for providing web services. Running the website on the system is just the ideal opportunity to test these services and prove to the Prolog community that they are a vital piece of the infrastructure and that we trust them. The server:

  welcomes about 4,000 visitors each day, viewing about 30,000 pages (120,000 hits) (2013)
  serves about 350 Gb of data per month
  serves downloads from static files
  serves manual pages from on-the-fly post-processed HTML documents
  serves dynamically generated HTML pages from documented source files, coloured source files, etc.
  analyses, indexes and presents packs. It also presents the meta-data for pack_install/1
  runs a REST API to handle user annotations.
Also see:

Can I replace a LAMP stack with SWI-Prolog?

https://www.swi-prolog.org/FAQ/PrologLAMP.txt


I was just responding regarding using Turing completeness as a gauge of usefulness. Although I don’t know it well at all, I think Prolog is an awesome language and would like to know it more.


> "What is "usefulness" then?"

"Usefulness" is that intangible quality that some tools have which make people overlook their unfriendly user interface, lacking documentation, brittle and crashy behaviour, inelegant design and push through that. "Uselessness" is that intangible quality or dealbreaker which means people who desire to use a pleasant or elegant or well-documented or stable tool, still cannot or do not, for any technical, practical or social reasons.

Clearly useful/useless varies with person and scenario: mandoline: sometimes useful to a cook; knife: sometimes useful to a lot of people. To me your other comment where you link to the Ackermann-Péter function on Rosettacode in successor arithmetics is the opposite of usefulness. Both versions solve ack(3,1,X) near enough instantly. The first with tabling solves ack(4,1,X) in a couple of seconds, and without tabling it overflows the stack even when I raise the stack limit to 8GB. Your version comments about how clean and elegant it is with Peano's axioms but it also stackoverflows ack(s(s(s(s(0)))), s(0), X) and that's with or without tabling. As far as I'm concerned, neither version is more readable than the other, they're both three lines of dense unhelpfully-named variable shuffling. You've turned something you think is inelegant but which works into something you think is more elegant, but works less well. Pleasing, maybe, but to me it's the opposite of useful.

It's like the people talking of RDF triples; Google them and read:

> "every part of an RDF triple is individually addressable via unique URIs — for example, the statement "Bob knows John" might be represented in RDF as:"

    http://example.name/#BobSmith12 http://xmlns.com/foaf/0.1/knows http://example.name/#JohnDoe34
Doesn't that just make you want to die? What could be more 1990s architecture astronauty, academic and impractical than turning "Bob knows John" into that mess? It's from a world of CORBA, SOAP, Jabber, Grid computing, SGML, and write papers about ontologies, not a world where people do useful things.

Or take the typical Prolog example of grandparent/parent/child family tree which might be academically pretty as an example of recursive search, but is basically useless in describing real world families with divorces, remarriages, foster parents, half-siblings, polygamy, unacknowledged offspring, children raised believing their grandmother was their mother and their mother was their sister, and all the rest of it. By the time code is extended like that it's more "useful" and less academically elegant, and by the time you've handled input and output and database formats and error messages and UX you may as well not be writing it in Prolog for all the difference it makes.

Or take the typical Prolog example of linguistic programming making sentences like "the cat sat on the mat" with a grammar which, after you squint a bit, you realise is equivalent to this brute force Python:

    for creature in ['cat', 'dog']:
      for verb in ['sat', 'lay']:
        for article in ['a', 'the']:
          for object in ['mat', 'chair']:
            print(creature, verb, 'on', article, object)
and that brute forcing all combinations is not especially performant, elegant, or useful, just because the grammar is pretty, and you aren't fooling anyone by writing verb as 'v' and noun as 'nn' and determiner as 'det' to make it look mathematical, and trees don't describe real use of language very well e.g. "Sound, mate - later!", or "okay, you do you".

"Usefulness" then is going in the other direction, it's the things which are inelegant, ugly, clunky, not well founded on beautiful theory, but still compelling enough to be widely used; C and C++ shipping Linux and Windows and macOS and Chrome and FireFox and 3D game engines and JavaScript V8 engine and Java JVM and .Net CLR and SWI Prolog engine and SQLite and SQL Server and PostgreSQL and Oracle and Rust shipping Scryer Prolog, Python or Swift cobbled over TensorFlow shipping workable ML models, Objective-C building most iOS apps, Go shipping Kubernetes, it's Lua being used as an embedded extension language, Perl writing shell scripts, AWK being small and quite low dependency and self-contained, JavaScript sustained by browser support, Excel or SMTP sustained by network effects.

It's not about arguing whether people 'could' use a thing, it's some intangible qualities that mean people actually do use a thing without trying to prove anything. For example, in T-SQL you cannot write "select a,b,c, from thing" because it complains about the trailing comma after the select list. That's annoying because I rarely write the correct thing first time and often edit the select list while I'm working, hitting that annoyance over and over. In SWI Prolog I can't write "?- test(X), % foo(Y)." because it complains about the trailing comma. That's anoying because I rarely write the correct thing first time, etc. If your instinct is to argue that the comma is meaningful, you're in academic feel-superior useless territory. In JavaScript arrays like "x = [1,2,3,];" used to error because of the trailing comma, somehow it was fixed so that's fine and it's a list of three items. If you're on that side of things, that's useful practical territory.

SWI Prolog's error messages are often useless for understanding what's gone wrong; "argument insufficiently instantiated in {term-expanded deep CLPFD internals}" or "{expanded foldl or maplist internals}" rarely helps find the problem. If your feeling on reading that is either "works for me, wontfix, get good" or "FOSS maintainers don't owe you anything check your entitlement", that can be completely correct and also in useless territory. Rust developers, realising they had an uphill battle to get anyone to care at all, spent a lot of effort on quality of life things like error messages and Cargo behaviour instead of turning people away for being entitled. Canonical did their "thousand papercuts" project for Ubuntu realising it needed more than "if you don't like it, don't use it /smug" to improve Linux on the desktop to the point where people wanted to use it, and one way or another it has become one of the most widely used distros.


Regarding the Peano version of the Ackermann-Péter function, I checked again to make sure and I never used the word "elegant" anywhere, either on HN or on Rosetta Code. I would never be so presumptuous, you know? On Rosetta code I pointed out that my version is "pure" because that's what Prolog code without side-effects is usually called. I put it in "quotes" because I personally don't care about purity.

What I care about is simplicity of structure. That's because the simpler the structure of a program, the easier the prorgam can be learned. You see, my PhD studies and my research interest are about writing Prolog programs that learn Prolog programs from Prolog programs and to do that it really helps if all the Prolog programs are veeery simple, for combinatorial explosion ever lurks.

For example, I'm so delighted that I figured out how to write that "pure" version of the Ackermann-Péter function not because I'm so full of myself I think it's "elegant" but because it is simple, and thanks to its simplicity I could then get my ILP system, Louise, to learn it from a single example:

https://github.com/stassa/louise/blob/master/data/examples/a...

The is/2 version would be much harder to learn, because of the more complex structure. Although I think Louise can do that too. Btw, I got Louise to learn the Function because I was challenged to do it by one of the examiners in my viva, who figured the Function's furious combinatorial complexity makes it unlearnable. That's right, but Louise can get around that because it can learn recursive programs with arbitrary structure from a single example, so it doesn't have to be trained on any example that triggers the Function's combinatorial fury. In any case, Ackermann is a toy function only really useful to make a point about recursion, and that's exactly how I use it also. Who cares if it blows up with n = 2, m = 4, or with n = 5, m = 6? It blows up quickly anyway. That's the whole point.

So, your comment above is very stream-of-consciousness and I wonder what motivated you to write such a mad rant of the internets. I guess you must be really passionate about the subject you discuss. If so, I understand. You are not alone :) No, really, I generally agree with you. I asked above what is "usefulness" because for me Prolog is useful and I don't understand why anyone would say it isn't. Reading your other comment in the thread, I got the impression you would agree with me on that.

But it's not about agreement. Aye, the night is long and full of errors and we must somehow deal with the dirty, dirty real world. Personally, I'm happy with that. But I do like my tools to also be nice to look at and I find that when I can make them so, they also tend to work better. For example, cleaner, better commented code, is easier to read and maintain. I mean, duh. In any case, in my mind, a well-made tool is a thing of beauty anyway you look at it.

Re: "quality of life", well yea, that. If you were to look at my Louise, I think you'd find that I've gone out of my way to make it into a system that people can used. I'm totally inspired to do that by SWI-Prolog, btw. So for example, Louise has logging facilities up the wazoo and so everytime someone tries to use it and it breaks, they send me a nice, friendly dump of their logs, and then I can trudge through them and help my user. Because I want to help my user. I wish people sent me more bug reports, but I guess the majority find that something breaks and they don't bother to tell me. Oh mon dieu, la cruelle tourmente.

As another example, I spent considerable effort to make sure that Louise's "metarules" (second-order background knowledge) are easy to read and use. For that purpose there's three metarule formats that Louise's pretty-printer can produce. One is the internal representation of the metarule that's useful for debugging, one is the user-friendly format where metarules are declared at the user-level and a final one is the formal notation, with quantifiers, used in the literature, so users can directly relate the metarules they use to a paper they read. Here's what that looks like ("chain" is the friendly identifier of that particular metarule):

  ?- print_metarules(expanded, chain).
  m(chain,P,Q,R):-m(P,X,Y),m(Q,X,Z),m(R,Z,Y)
  true.
  
  ?- print_metarules(user_friendly, chain).
  configuration:chain metarule 'P(x,y):- Q(x,z),R(z,y)'.
  true.
  
  ?- print_metarules(quantified, chain).
  (Chain) ∃.P,Q,R ∀.x,y,z: P(x,y)← Q(x,z),R(z,y)
  true.
By contrast, if you look at the original Meta-Interpretive Learning system, Metagol (https://github.com/metagol/metagol), this is what "chain" looks like:

  metarule([P,Q,R], [P,A,B], [[Q,A,C],[R,C,B]]). % chain
If I understand your comments about "quality of life" work correctly, then that's pretty much what I always try to do and what most people in academia never do. Guess what, I'm out of the game now. But, well, at least I tried :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: