Hacker News new | ask | show | jobs
by tom_mellior 3547 days ago
> There's a joke that writing a compiler in Prolog is trivially easy; but writing a compiler in Prolog that does anything other than say 'No.' when given an invalid program is infeasibly hard.

I realize you said this was a joke, but still... A compiler in Prolog might look like this:

  compile(Input, Output) :-
      parse(Input, AST),
      process(AST, Output).
and this does, indeed, just answer "no" or "false" when it fails. But you can improve it by just doing something like this:

  compile(Input, Output) :-
      (   parse(Input, AST)          % if parsing succeeds...
      ->  process(AST, Output)       % ... then process the AST...
      ;   writeln('syntax error')    % ... otherwise report an error
      ).
Or you can just use exceptions, which also exist in Prolog. Of course you'd need to collect data (line, column, expected next construct) during parsing in order to make the error message nicer.

> I generally found that while getting Prolog to do cool things was fairly straightforward, getting Prolog to do cool things quickly involved knowing precisely where to put cut operators, and that was basically black magic.

The cut is indeed complex, and for historical reasons it's taught too early and emphasized too much by almost all Prolog classes and books. For example, most resources would tell you to write the example above as:

  compile(Input, Output) :-
      parse(Input, AST),
      !,    % commit to this choice if parsing succeeded
      process(AST, Output).
  compile(_Input, _Output) :-
      % we get here by funky implicit control flow if parsing failed
      writeln('syntax error').
It's not that hard to understand the cut once you have a good understanding of normal Prolog execution, but yes, that has to come first. And once you understand how it works, you can often find better solutions that do not use the cut.

As for writing "low-level" code like GUIs, you just use your Prolog system's foreign function interface....

1 comments

As I say, it's been years. I don't recall -> and ; at all. (Was there ever a time when they weren't in the language?) They look much nicer than cut and the implicit control flow.

I am, actually, right now struggling with priority-and-constraint-based register allocation and instruction selection for a compiler backend. It is so the right kind of problem for Prolog.

There's nothing funny about ';': it's just 'or'. Combined with '->', which means 'then', it essentially comes to behave like an 'else'.

';' has been in the language since the beginning, and I'm pretty sure '->' was too, but can't say for sure.

I think -> is newer, but it's in ISO Prolog, which came out in 1995. So it's rather likely that the OP learned Prolog at a time when -> existed but teaching resources had not caught up. Not sure if that's the case even now.
I learned Prolog back in 1997, so it may have existed in the implementations I used back then. Must see if I can find an implementation of HU Prolog from back then. I also used SWI Prolog from back then, and I'd expect that was more up to date.

Edit: mention SWI Prolog.