Of course intros to other languages may gloss over I/O as well, but with mainstream imperative languages (that aren't oriented to defining and querying data), it's more well known or assumed that the standard I/O patterns apply.
Of course intros to other languages may gloss over I/O as well, but with mainstream imperative languages (that aren't oriented to defining and querying data), it's more well known or assumed that the standard I/O patterns apply.
You're right about that and I don't think it's a minor thing. One reason is that most tutorials have a hard enough time going through everything you need to know before you can start parsing json and writing out to file, without getting stuck in infinite recursion etc. so the nitty-gritty of day-to-day programming work is often left as an exercise for the reader.
On the other hand, I have the feeling that many people check out Prolog to see how it's different then go looking for the way to do the usual things in it. This may be the wrong approach. Prolog has some advanced features and those are "the whole point" about the language. If all you'll ever need to do is process some csv, there's probably no point in going through all the hard work to learn Prolog- you can do it in another language rather more easily.
That said, the Swi-Prolog homepage has a link to a good tutorial on creating web applications with it that I recommend to anyone interested in that sort of thing:
It's under the "Tutorials" header. Unfortunately my phone's ISP is blocking it so I can't link directly to it. Harumph.
As for Prolog, I get the sense that it is implied that it is an "information/data language", and it is thought a little like how SQL is taught - only, you're only given the SQL parser and building the clustered, relational backend is left as an exercise to the reader, as well as bulk import/export and backup/restore systems.
However, once you start bolting on side effects, like I/O and asserting/retracting facts in the middle of queries, all declarativeness flies out the window and you're left trying to explicitly juggle the implicit branching and control of the program counter to try to keep the system sane, bringing in more and more of the complexities of imperative programming. Optimization also basically requires wresting control of the program counter back from the abstract system into explicit programmer control.
It certainly works as part of practical real-world systems, but I wouldn't necessarily want to write a large, behavior-heavy application purely in Prolog. For large in-RAM data, but light on behavior stuff, fine. There are certain data analyses that are much faster to develop in Prolog than imperatively, and going multi-language can save a lot of programmer time compared to writing everything in $TRADITIONAL_LANGUAGE purely out of inertia.
I'm unsure what this alludes to. Are you talking about minding tail-call optimisation? That's not a feature of Prolog only.
>> going multi-language can save a lot of programmer time compared to writing everything in $TRADITIONAL_LANGUAGE purely out of inertia
A better idea is to chuck out most of your stack and write most of your application in Prolog itself- no xml, no having to worry about Object-Relational Impedance Mismatch, and so on. You don't even need regular expressions, because writing a compiler in prolog with Definite Clause Grammars is a piece of cake (something that can't be said for any other language under the sun).
For instance, see "Can I replace a LAMP stack with Prolog?", here:
Many of the optimizations I've seen are ensuring that no branches are explored that the programmer knows are irrelevant once certain unifications have succeeded, and to control the ordering of branch exploration to try to find faster answers first. Indexing is also manual, and while I haven't looked in a few years, I haven't seen any JIT-style heuristic feedback that lets the system optimize itself for the runtime conditions of Prolog programs.
In my definitions, which some certainly argue against, declarative means you let the CPU do "whatever it takes" in the background, while imperative has you directly managing where the program counter goes, in what order, including explicit thread management (which Prologs that I've seen make you do as well).
OK, you're talking about the cut here. I've made some more comments on it above, but basically I don't really see what the problem is, with it. It strikes me as more of a theoretical point to have to worry about.
Prolog takes a practical approach to both logic programming and the whole declarativeness thing. That is to say, if you can't have efficiency, you sacrifice some purity so that you can have a language that lets you do work. The cut, along with other program flow control predicates (->/0, ;/0 etc) and predicates with side-effects (write/1, get0/1 etc) are normally discussed under "extra-logical facilities" or some such section of textbooks.
We all all understand first-order logic inference is intractable, but we want to run it as a programming language so concessions must be made to material reality. Same goes for every other language- computing efficiently is one half of programming computers (untangling the mess you make is the other half).
This is a very old line of criticism and I don't really see the point of it anymore- not after having learned how to use the cut without hurting myself. So maybe it's just a problem in principle, because in practice it's not such a big deal.
>> Indexing is also manual, and while I haven't looked in a few years, I haven't seen any JIT-style heuristic feedback that lets the system optimize itself for the runtime conditions of Prolog programs.
Swi-Prolog has JIT clause indexing:
http://www.swi-prolog.org/pldoc/man?section=jitindex
The first argument of coumpound terms is indexed, as long as it's atomic- so you do need to understand indexing to make best use of it. I mention a recent case were I made a mess and then untangled it once I realised how I was using indexing wrong.
So, you need to know some programming, right? I don't see that as a bad thing.
>> explicit thread management (which Prologs that I've seen make you do as well).
For multithreaded applications, that's true. I don't know how much of a problem is that in practice because I've never really had to use the facilities, but at least you got immutability to protect you from the usual pain.
These concessions are a bad thing if the goal is to work in a new model of programming distanced from the complexities and bugs of imperative programming. These concessions bring back the same class of bugs and problems, exemplified by "oh, you just have to learn how not to have your program self-destruct by using this low-level operation incorrectly" in a declarative language.
I'd have no problems with replacing replacing green cuts and implicit ordering with separate non-invasive hint declarations, instead of exposing low-level backtracking munging operations which can be used in odd and destructive ways (and we in fact did so in our internal prolog-inspired languages). The presence of these types of operations and constraints also means the compiler often can't reorder clauses if it can (statically or dynamically) determine that one ordering is better than another.
Taking a mostly declarative language and throwing in cut, inline io/assertions/retractions when backtracking can occur, and demanding the execution follow the lexical order of all clauses is basically like throwing raw C pointers into Java: It seems to go against the language's design intent. It's a hack to get things going back when computers were too small & slow to have smarter compilers, and these hacks bring with them otherwise completely unnecessary problems. I don't think they should be defended, but viewed as warts that hopefully the language can design past in the future.
At the end of it: 1) you didn't learn to read or write text to the console. 2) You are unable to make any useful program, let alone a hello world.
This kind of non-practical training materials is a recurring issue with functional languages.
It's a recurring theme when teaching languages to do it through something the author (maybe implicitly) consider a good fit, something that emphasise the beauty of that particular language.
Might be good while you are learning your first language, maybe ?
This explains the IO/side effect heavy imperative tutorials, the structure rich OO tutorials, the 'algorithmic' FP ones, etc. Turned upside down quite clearly tells you which language is strong in a particular area, and complicated/awkward in another.
Myself, I prefer to start with the ugly parts, they contain much more information about the tradeoffs and focus of any particular language.