Lessons/Hello World!

From wiki.visual-prolog.com

In this lesson we will just write some code disregarding the finer details.

Exercise Create a console project.

Double-click the main.pro file in the project tree to open it in an editor, and update the run clauses to look like this:

    run() :-
        stdio::write("Hello World!\n").
Run the program using Build -> Run in window Alt+F5.

The main.pro file contains other stuff, which we will currently disregard, and focus solely on the run clauses you just wrote.

First we have the keyword clauses, which simly indicates that what comes after are clauses. Clauses is where the actual running code is written.

In this text I will use words like "clause" and "predicate", which all have their origin in formal logic, but for the moment we will simply treat them as the names that happens to be chosen for things in a Prolog program.

clauses are used to define predicates, where a predicate is a Prolog routine/subroutine/function/procedure (dear child has many names)

This particular clause defines a predicate run which takes no arguments (indicated by the empty parentheses ()).

After the :- token we have the code that will be executed when run is invoked/called.

In this case we call a predicate named write which is defined in the class named stdio. We will discuss classes later for now we will just consider stdio::write as "a long compound name".

We supply one argument, i.e. the string literal "Hello World!\n", to the stdio::write predicate. Notice that \n in the string literal represents a line shift.

The clause is terminated by a period (i.e. .). Period is used as terminator for many kinds of entities in Visual Prolog.

The predicate run is called when the program is run, and acts as our entry point to the program. Actually, the real entry point is the goal a further down in the main.pro file, but that entry point is used to make varous initializations, corresponding clean-up, etc and will call the run predicate in the right spot, so run can act like your entry point.

So when the program is run the predicate run in main.pro will be called and this will (here) call stdio::write with the argument "Hello World!\n", as a result Hello World! and a line shift will be written to the console window.

Actually, stdio::write writes to the standard output stream, which in a console program is initialized to be the console window. In a default GUI program the standard output stream will write to a message window, but the standard output stream is under programmer control, so what happens when you call stdio::write will depend of what has taken place in the program.

To summarize:

  • The actual running code is in clauses
  • predicates is the Visual Prolog name for routines/subroutines/functions/procedures.
  • Predicates are organized in classes, and predicates from other classes is referenced using <class>::<predicate>.
  • The run predicate in main.pro is the (effective) entry to a program.
  • stdio::write can write to the standard output stream

Now let us extend the program with an extra predicate.

Exercise Add this code below the run clauses:
class predicates
    advancedHello : (string Name).
    advancedHello(Name) :-
        stdio::writef("Hello %!\n", Name).
Build the project using Build -> Build Ctrl+Shift+B

When you build the project you will get a warning stating that the predicate main::advancedHello is an unused local predicate. Which is completely correct; we haven't used it for anything. But let us "decipher" it before we go any further.

We notice that we again have a clause in a clauses section. The clause is for a predicate named  advancedHello that takes one argument called Name. Name is a variable, a variable starts with an uppercase letter and will be green in the editor (variables can also start with an underscore, but we will discuss that later).

Name acts as a formal parameter representing the actual argument used in the call to advancedHello. In this clause we call stdio::writef which is a more advanced "writer" predicate. The first argument to writef is a format string, which contains a %-character, what happens when writef is called is that the actual value of Name is substituted into the format string in the place where the %-character is and then the resulting string is written to the standard output.

This time we also have a class predicates section containing a declaration of the advacedHello predicate. This perticular declaration declares advancedHello as a class predicate which takes one argument which must be a string.

In the predicate declaration the argument also have the name Name but in the declaration the name is mainly intended for documentation purposes. The variable name in the declaration and in the clauses can be different, or you can remove it completely. I recommend that you always have variable names here and that you use variable names that will make it clearer for the user of the predicate what the arguments represents.

What it means to be a class predicate and what else a predicate can be is discussed elsewhere/later. But before we leave the subject try this little experiement:

Exercise Remove the word class from class predicates in the declaration of advancedHello. And then build the project.

Notice the error message and remember that you get this message when you have forgotten to write class in front of predicates.

Then insert class again and build the project again.

Now that we have the advancedHello predicate we can use it in our run predicate.

Exercise Update the run clause to look like this:
    run() :-
Run the project in a window.

The clause should be understandable, I just want to highlight that we have used comma to separate the two invocations of advancedHello: comma" to separate, period to terminate. I will give a little prediction: Later when you are familiar with Visual Prolog you will from time to time make syntax errors and (the prediction) 9 out of 10 times the syntax error will concern comma and/or period.

To summarize:

  • Predicates must have a declaration (run is also declared we just havn't looked at its declaration).
  • Arguments in predicates declarations can be given names that clarify the meaning if the arguments.
  • stdio::writef writes text to the standard output stream using a format string.
  • calls are separated by comma and clauses (and predicate declarations) are terminated by period.
  • If I get a syntax error it is likely to be related to comma or period.
  • A certain other error message (can you recall it) probably means that I have forgotten to write class in front of predicates.