Learning Prolog: Lab Session #4 - Reading and Writing
This week we were asked to do another 2 labs in one session - this blog post will cover lab #4, and there will be another one coming out on Thursday for lab #5.
Before we start though, I want to mention Swish. It's an online editor for Prolog that runs in the browser. It apparently doesn't support all the features that the desktop version does, but the editor itself is so much better than the desktop version. It's actually bearable! If at all possible, I'll be using it from now on.
This week's (first) lab was all about reading and writing from the console. You would have thought that this would be the first thing you'd learn as a hello world, but apparently that isn't the case. 3 weeks into the course, and we finally know enough to write our first hello world in Prolog!
Anyway, reading and writing are quite simple actually - once you've learnt rules. Here's an example:
go :- write('Hello, world!').
If you query
go. on the above, you should get an output something like this:
?- go. Hello, world! true
write/1 (write arrity 1) statement lets us write out a message to the console. Note that the string we want to output is enclosed in single quotes. This is important, because apparently some Prolog environments interpret double quotes to mean "output the ASCII character codes of the characters in this string", and not "output the characters themselves in this string". Personally I haven't found that to be the case, but it's best to be aware of it.
Writing messages to the console is neat, but not particularly useful in itself. Let's upgrade it to ask the user's name, and then say hello to them:
go :- write('Enter name: '), read(Name), write('Hello, '), write(Name), write('!'), nl.
Here's an example output:
?- go. Enter name: |: starbeamrainbowlabs. Hello, starbeamrainbowlabs! true.
When you ask Prolog
go., it then asks you what your name is - and then says hello to you. There are several things to note here. Firstly,
nl/0 is a special predicate that simply write a newline character to the console. Secondly,
read/1 is a special predicate to read in a string from the console and drop it into the given variable.
read/1 can be rather weird when it comes to actually getting input from the user. The string the user enters must be terminated by a full stop (
.), otherwise it will continue to ask for input. It must also start with a lower case letter, otherwise strange stuff starts to happen. I theorise that this is probably related to the fact that variables in Prolog start with an uppercase letter.
Thankfully, we can get around the second issue by enclosing strings in double quotes:
?- go. Enter name: |: 'Starbeamrainbowlabs'. Hello, Starbeamrainbowlabs!
Much better. Let's actually use these new functions to do something (kind of) useful. Here's the first excercise:
Write a Prolog program using facts in the form month/1 that displays the month depending on the integer entered by the user, e.g. if the user enters 3 the program will display The Month is March.
Initially I was started with a program beginning like this:
month(January) :- % ...
But soon found that it didn't work. The solution here is to invert it, so that Prolog gets to choose which path it takes based on the input it gets. It makes sense, I suppose, considering Prolog is a language for writing artificial intelligences.
Here's some example output:
?- month(1). January true. ?- go. Enter month code: |: 4. April true.
In the above, we can either
month/1 directly, or query
go., which will ask us for the month code directly and call
month/1 for us.
That concludes the 4th lab. I'll write up another post for lab #5, which should hopefully be out on Thursday. As an aside, I used the embed code from PasteBin in this post instead of embedding the code directly and then linking to the PasteBin. Which would you prefer? Why? Do you have another idea? Let me know in the comments!