Notes
For
Notes about if-then-else (and soft-cut)
Extensive Stack Overflow discussion
https://stackoverflow.com/questions/2849045/if-in-prolog
See also
"if_/3 and related predicates" in
Higher-order Predicates by Markus Triska
Did you know ... | Search Documentation: |
Predicate ->/2 |
If -> Then; _Else :- If, !, Then. If -> _Then; Else :- !, Else. If -> Then :- If, !, Then.
Please note that (If ->
Then) acts as (If ->
Then ;
fail), making the construct fail if the condition fails.
This unusual semantics is part of the ISO and all de-facto Prolog
standards.
Please note that (if->
then;else) is read as ((if->
then);else)
and that the combined semantics of this syntactic construct as
defined above is different from the simple nesting of the two
individual constructs, i.e., the semantics of
->/2 changes
when embedded in ;/2. See
also
once/1.
As with ;/2, this construct is always nested in parenthesis. Here is an example of the preferred layout for SWI-Prolog.
p :- a, ( b, c -> d, e ; f -> g ; h ).
With the help of library(csv) and library(http/json), we read a CSV file and use the column names in the first row to emit JSON.
For this example, we use the file weather.csv
:
city,temp_lo,temp_hi,prcp,date San Francisco,46,50,0.25,1994-11-27 San Francisco,43,57,0,1994-11-29 Hayward,37,54,,1994-11-29
The script csv_to_json.pl
reads the CSV from standard input or from
the file provided as the first argument of the script. It converts
the contents to a list of dicts, then writes this as JSON to standard
output:
:- initialization(main, main). :- use_module(library(csv)). :- use_module(library(http/json)). main :- ( current_prolog_flag(argv, [CSV_file|_]) -> csv_read_file(CSV_file, CSV, []) ; csv_read_stream(current_input, CSV, []) ), CSV = [Colnames|Rows], Colnames =.. [row|Names], maplist(row_dict(Names), Rows, Dicts), json_write_dict(current_output, Dicts, [null('')]). row_dict(Names, Row, Dict) :- Row =.. [row|Fields], pairs_keys_values(Data, Names, Fields), dict_create(Dict, _, Data).
The null('')
option to json_write_dict/3 is necessary to convert the
empty "prcp" field in the last row to a missing value represented as
null
in the JSON output.
This is how we can use it to convert weather.csv
to JSON:
$ swipl csv_to_json.pl weather.csv [ { "city":"San Francisco", "date":"1994-11-27", "prcp":0.25, "temp_hi":50, "temp_lo":46 }, { "city":"San Francisco", "date":"1994-11-29", "prcp":0, "temp_hi":57, "temp_lo":43 }, { "city":"Hayward", "date":"1994-11-29", "prcp":null, "temp_hi":54, "temp_lo":37 } ]
file_line(File, Line) :- setup_call_cleanup(open(File, read, In), stream_line(In, Line), close(In)). stream_line(In, Line) :- repeat, ( read_line_to_string(In, Line0), Line0 \== end_of_file -> Line0 = Line ; !, fail ).
This will backtrack over consecutive lines in the input. If we use the Unix dictionary words:
?- file_line("/usr/share/dict/words", Word). Word = "A" ; Word = "a" ; Word = "aa" ; Word = "aal" ; % and so on
This doesn't load all lines to memory, so it can be used with very large files.
This shows how to convert almost any "string" of 0s and 1s to an integer.
It takes advantage of the built-in term reading, thus avoiding an explicit loop and arithmetic.
binary_string_to_int(Str, Int) :- ( ( string(Str) ; atom(Str) ) -> atomics_to_string(["0b", Str], Literal) ; is_list(Str) -> atomics_to_string(["0b"|Str], Literal) ; type_error(string_type, Str) ), catch(term_string(Int, Literal, []), error(syntax_error(_), _), type_error(string_of_0s_and_1s, Str)).
?- binary_string_to_int('101', X). X = 5. ?- binary_string_to_int([0, 0, 1, 0, 1], X). X = 5. ?- binary_string_to_int(["1", "1", "0"], X). X = 6.
For
Notes about if-then-else (and soft-cut)
https://stackoverflow.com/questions/2849045/if-in-prolog
"if_/3 and related predicates" in
Higher-order Predicates by Markus Triska