patternMinor
cat program in Prolog
Viewed 0 times
prologprogramcat
Problem
In order to learn Prolog, I have implemented the
File
File
Note: I'm using SWI-Prolog.
cat command in Prolog. I want to know if the code is idiomatic and what could be improved.File
args.pl::- module(args, [withFilesOrUserInput/2]).
withFilesOrUserInput(StreamFunction, []) :-
call(StreamFunction, user_input).
withFilesOrUserInput(StreamFunction, [Filename]) :-
withFile(StreamFunction, Filename).
withFilesOrUserInput(StreamFunction, [Head|Tail]) :-
withFile(StreamFunction, Head),
withFilesOrUserInput(StreamFunction, Tail).
withFile(StreamFunction, Filename) :-
open(Filename, read, StreamIn),
call(StreamFunction, StreamIn),
close(StreamIn).File
cat.pl::- use_module(args).
main(Argv) :-
prompt(_, ''),
withFilesOrUserInput(catStream, Argv).
catStream(Stream) :-
copy_stream_data(Stream, user_output),
flush_output(user_output).Note: I'm using SWI-Prolog.
Solution
+1, good question.
The Prolog convention is to use underscores for readability. Why?
A good naming convention is to use one noun per argument, declaratively describing what the argument stands for.
In SWI-Prolog, check out
The advantage is clear: You can then readily test your predicates on the toplevel alone, without even requiring a file, just by stating the input as a regular Prolog term.
This helps a lot also when writing test cases.
EDIT: I give you one example how DCGs can help you here. It is not yet completely pure, because this DCG contains output itself. However, it is much simpler than your code, and you can test this predicate without even needing a file, and then transparently apply the same code to a file too:
This DCG describes a list of character codes, and outputs each code.
Sample use:
Now, with
?- once(phrase_from_file(cat, 'cat.pl')).
With output:
i.e., the same program as above, which I had saved it
I am using
The Prolog convention is to use underscores for readability. Why?
because_it_is_easy_to_read_even_long_names_with_underscores, butItIsExtremelyHardToReadEvenShorterNamesWithMixedCaps!A good naming convention is to use one noun per argument, declaratively describing what the argument stands for.
In SWI-Prolog, check out
library(pio): The pure way to do what you want is to use a DCG to describe a list, and then to use phrase_from_file/2 to apply the DCG to a file.The advantage is clear: You can then readily test your predicates on the toplevel alone, without even requiring a file, just by stating the input as a regular Prolog term.
This helps a lot also when writing test cases.
EDIT: I give you one example how DCGs can help you here. It is not yet completely pure, because this DCG contains output itself. However, it is much simpler than your code, and you can test this predicate without even needing a file, and then transparently apply the same code to a file too:
:- use_module(library(pio)).
:- set_prolog_flag(double_quotes, codes).
cat --> [].
cat --> [C], { put_char(C) }, cat.This DCG describes a list of character codes, and outputs each code.
Sample use:
?- phrase(cat, "test").
test
true.Now, with
phrase_from_file/2 from Ulrich Neumerkel's library(pio), we can transparently apply the same DCG to a file too:?- once(phrase_from_file(cat, 'cat.pl')).
With output:
:- use_module(library(pio)).
:- set_prolog_flag(double_quotes, codes).
cat --> [].
cat --> [C], { put_char(C) }, cat.i.e., the same program as above, which I had saved it
cat.pl.I am using
once/1 to commit to the first solution found (there is no further solution, but a choice-point left).Code Snippets
:- use_module(library(pio)).
:- set_prolog_flag(double_quotes, codes).
cat --> [].
cat --> [C], { put_char(C) }, cat.?- phrase(cat, "test").
test
true.:- use_module(library(pio)).
:- set_prolog_flag(double_quotes, codes).
cat --> [].
cat --> [C], { put_char(C) }, cat.Context
StackExchange Code Review Q#101982, answer score: 5
Revisions (0)
No revisions yet.