From 7a2981e21cded69780c8215709fe4ac782ddad76 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 17:32:06 +0200 Subject: [PATCH 1/6] include usage advice about probabilistic predicates --- src/prolog/lib/random.pl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/prolog/lib/random.pl b/src/prolog/lib/random.pl index 7e59fc23..5fee57e0 100644 --- a/src/prolog/lib/random.pl +++ b/src/prolog/lib/random.pl @@ -1,5 +1,11 @@ :- module(random, [maybe/0, random/1, random_integer/3, set_random/1]). +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + To retain desirable declarative properties, predicates that internally + use random numbers should be equipped with an argument that specifies + the random seed. This makes everything completely reproducible. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + % succeeds with probability 0.5. maybe :- '$maybe'. From 2b1692a8600b6dcb18429210fa03b0f78a7b6cc8 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 17:34:47 +0200 Subject: [PATCH 2/6] ADDED: library(error): instantiation_error/1, domain_error/3, type_error/3 These predicates simplify throwing ISO errors. --- src/prolog/lib/error.pl | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/prolog/lib/error.pl b/src/prolog/lib/error.pl index 6fb573a4..83111884 100644 --- a/src/prolog/lib/error.pl +++ b/src/prolog/lib/error.pl @@ -1,5 +1,9 @@ :- module(error, [must_be/2, - can_be/2]). + can_be/2, + instantiation_error/1, + domain_error/3, + type_error/3 + ]). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Written September 2018 by Markus Triska (triska@metalevel.at) @@ -32,10 +36,10 @@ must_be(Type, Term) :- must_be_(Type, _) :- var(Type), - instantiation_error(Type). + instantiation_error(must_be/2). must_be_(var, Term) :- ( var(Term) -> true - ; throw(error(uninstantiation_error, _)) + ; throw(error(uninstantiation_error, must_be/2)) ). must_be_(integer, Term) :- check_(integer, integer, Term). must_be_(atom, Term) :- check_(atom, atom, Term). @@ -43,12 +47,12 @@ must_be_(list, Term) :- check_(ilist, list, Term). must_be_(type, Term) :- check_(type, type, Term). check_(Pred, Type, Term) :- - ( var(Term) -> instantiation_error(Term) + ( var(Term) -> instantiation_error(must_be/2) ; call(Pred, Term) -> true - ; type_error(Type, Term) + ; type_error(Type, Term, must_be/2) ). -ilist(V) :- var(V), instantiation_error(V). +ilist(V) :- var(V), instantiation_error(must_be/2). ilist([]). ilist([_|Ls]) :- ilist(Ls). @@ -76,7 +80,7 @@ can_be(Type, Term) :- must_be(type, Type), ( var(Term) -> true ; can_(Type, Term) -> true - ; type_error(Type, Term) + ; type_error(Type, Term, can_be/2) ). can_(integer, Term) :- integer(Term). @@ -92,11 +96,11 @@ list_or_partial_list([_|Ls]) :- Shorthands for throwing ISO errors. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -instantiation_error(_Term) :- - throw(error(instantiation_error, _)). +instantiation_error(Context) :- + throw(error(instantiation_error, Context)). -domain_error(Type, Term) :- - throw(error(domain_error(Type, Term), _)). +domain_error(Type, Term, Context) :- + throw(error(domain_error(Type, Term), Context)). -type_error(Type, Term) :- - throw(error(type_error(Type, Term), _)). +type_error(Type, Term, Context) :- + throw(error(type_error(Type, Term), Context)). From 8e1ba58551d3158eff6465bb86b90c9612fe0175 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 17:42:05 +0200 Subject: [PATCH 3/6] use new predicates from library(error) --- src/prolog/lib/arithmetic.pl | 10 ++++++---- src/prolog/lib/clpb.pl | 8 +------- src/prolog/lib/clpz.pl | 9 +-------- src/prolog/lib/format.pl | 9 +++------ src/prolog/lib/pio.pl | 5 +++-- src/prolog/lib/random.pl | 12 +++++++----- src/prolog/lib/time.pl | 3 ++- 7 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/prolog/lib/arithmetic.pl b/src/prolog/lib/arithmetic.pl index ab691a09..406e8473 100644 --- a/src/prolog/lib/arithmetic.pl +++ b/src/prolog/lib/arithmetic.pl @@ -1,9 +1,11 @@ :- module(arithmetic, [msb/2, lsb/2]). +:- use_module(library(error)). + lsb(X, N) :- builtins:must_be_number(X, lsb/2), - ( \+ integer(X) -> throw(error(type_error(integer, X), lsb/2)) - ; X < 1 -> throw(error(domain_error(not_less_than_one, X), lsb/2)) + ( \+ integer(X) -> type_error(integer, X, lsb/2) + ; X < 1 -> domain_error(not_less_than_one, X, lsb/2) ; builtins:can_be_number(N, lsb/2), X1 is X /\ (-X), msb_(X1, -1, N) @@ -11,8 +13,8 @@ lsb(X, N) :- msb(X, N) :- builtins:must_be_number(X, msb/2), - ( \+ integer(X) -> throw(error(type_error(integer, X), msb/2)) - ; X < 1 -> throw(error(domain_error(not_less_than_one, X), msb/2)) + ( \+ integer(X) -> type_error(integer, X, msb/2) + ; X < 1 -> domain_error(not_less_than_one, X, msb/2) ; builtins:can_be_number(N, msb/2), X1 is X >> 1, msb_(X1, 0, N) diff --git a/src/prolog/lib/clpb.pl b/src/prolog/lib/clpb.pl index f373f83a..6b74e272 100644 --- a/src/prolog/lib/clpb.pl +++ b/src/prolog/lib/clpb.pl @@ -34,7 +34,7 @@ :- use_module(library(random)). :- use_module(library(pairs)). :- use_module(library(dcgs)). -:- use_module(library(error), []). +:- use_module(library(error), [domain_error/3, type_error/3]). :- attribute clpb/1, @@ -98,16 +98,10 @@ instantiation_error(_, Goal-Arg) :- domain_error(Expectation, Term) :- domain_error(Expectation, Term, unknown(Term)-1). -domain_error(Expectation, Term, Goal-Arg) :- - throw(error(domain_error(Expectation, Term), domain_error(Goal, Arg, Expectation, Term))). - type_error(Expectation, Term) :- type_error(Expectation, Term, unknown(Term)-1). -type_error(Expectation, Term, Goal-Arg) :- - throw(error(type_error(Expectation, Term), type_error(Goal, Arg, Expectation, Term))). - partition(Pred, Ls0, As, Bs) :- include(Pred, Ls0, As), exclude(Pred, Ls0, Bs). diff --git a/src/prolog/lib/clpz.pl b/src/prolog/lib/clpz.pl index f650cd3a..f9a4a91f 100644 --- a/src/prolog/lib/clpz.pl +++ b/src/prolog/lib/clpz.pl @@ -115,7 +115,7 @@ :- use_module(library(iso_ext)). :- use_module(library(dcgs)). :- use_module(library(terms)). -:- use_module(library(error), []). +:- use_module(library(error), [domain_error/3, type_error/3]). :- use_module(library(si)). :- use_module(library(freeze)). @@ -185,16 +185,9 @@ instantiation_error(_, Goal-Arg) :- domain_error(Expectation, Term) :- domain_error(Expectation, Term, unknown(Term)-1). -domain_error(Expectation, Term, Goal-Arg) :- - throw(error(domain_error(Expectation, Term), domain_error(Goal, Arg, Expectation, Term))). - - type_error(Expectation, Term) :- type_error(Expectation, Term, unknown(Term)-1). -type_error(Expectation, Term, Goal-Arg) :- - throw(error(type_error(Expectation, Term), type_error(Goal, Arg, Expectation, Term))). - partition(Pred, Ls0, As, Bs) :- include(Pred, Ls0, As), diff --git a/src/prolog/lib/format.pl b/src/prolog/lib/format.pl index b48a22ff..00f19638 100644 --- a/src/prolog/lib/format.pl +++ b/src/prolog/lib/format.pl @@ -148,7 +148,7 @@ element_gluevar(glue(_,V), N, N) --> [V]. cells([], Args, Tab, Es) --> ( { Args == [] } -> cell(Tab, Tab, Es) - ; { domain_error(no_remaining_arguments, Args) } + ; { domain_error(no_remaining_arguments, Args, format_//2) } ). cells([~,~|Fs], Args, Tab, Es) --> !, cells(Fs, Args, Tab, [chars("~")|Es]). @@ -253,15 +253,12 @@ cells([~|Fs0], Args0, Tab0, Es) --> cells(Fs, Args, Tab, []). cells([~,C|_], _, _, _) --> { atom_chars(A, [~,C]), - domain_error(format_string, A) }. + domain_error(format_string, A, format_//2) }. cells(Fs0, Args, Tab, Es) --> { phrase(upto_what(Fs1, ~), Fs0, Fs), Fs1 = [_|_] }, cells(Fs, Args, Tab, [chars(Fs1)|Es]). -domain_error(Type, Term) :- - throw(error(domain_error(Type, Term), _)). - n_newlines(0) --> !. n_newlines(1) --> !, [newline]. n_newlines(N0) --> { N0 > 1, N is N0 - 1 }, [newline], n_newlines(N). @@ -498,7 +495,7 @@ listing(PI) :- Arity = Arity0 ; PI = Name//Arity0 -> Arity is Arity0 + 2 - ; throw(error(type_error(predicate_indicator, PI), listing/1)) + ; type_error(predicate_indicator, PI, listing/1) ), functor(Head, Name, Arity), \+ \+ clause(Head, Body), % only true if there is at least one clause diff --git a/src/prolog/lib/pio.pl b/src/prolog/lib/pio.pl index 470d13fb..4f387625 100644 --- a/src/prolog/lib/pio.pl +++ b/src/prolog/lib/pio.pl @@ -1,11 +1,12 @@ :- module(pio, [phrase_from_file/2]). :- use_module(library(dcgs)). +:- use_module(library(error)). phrase_from_file(NT, File) :- - ( var(File) -> throw(error(instantiation_error, phrase_from_file/2)) + ( var(File) -> instantiation_error(phrase_from_file/2) ; (\+ atom(File) ; File = []) -> - throw(error(domain_error(source_sink, File), phrase_from_file/2)) + domain_error(source_sink, File, phrase_from_file/2) ; '$file_to_chars'(File, Chars), phrase(NT, Chars) ). diff --git a/src/prolog/lib/random.pl b/src/prolog/lib/random.pl index 5fee57e0..7f7803e3 100644 --- a/src/prolog/lib/random.pl +++ b/src/prolog/lib/random.pl @@ -6,6 +6,8 @@ the random seed. This makes everything completely reproducible. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +:- use_module(library(error)). + % succeeds with probability 0.5. maybe :- '$maybe'. @@ -22,9 +24,9 @@ random_integer(Lower, Upper, R) :- ( (var(Lower) ; var(Upper)) -> throw(error(instantiation_error, random_integer/3)) ; \+ integer(Lower) -> - throw(error(domain_error(integer, Lower), random_integer/3)) + domain_error(integer, Lower, random_integer/3) ; \+ integer(Upper) -> - throw(error(domain_error(integer, Upper), random_integer/3)) + domain_error(integer, Upper, random_integer/3) ; Upper > Lower, random(R0), R is floor((Upper - Lower) * R0 + Lower) @@ -47,11 +49,11 @@ rnd_(N, R0, R) :- set_random(Seed) :- ( nonvar(Seed) -> ( Seed = seed(S) -> - ( var(S) -> throw(error(instantiation_error, set_random/1)) + ( var(S) -> instantiation_error(set_random/1) ; integer(S) -> '$set_seed'(S) - ; throw(error(type_error(integer(S), set_random/1))) + ; type_error(integer, S, set_random/1) ) ) - ; throw(error(instantiation_error, set_random/1)) + ; instantiation_error(set_random/1) ). diff --git a/src/prolog/lib/time.pl b/src/prolog/lib/time.pl index 2c2b67c1..6fd68517 100644 --- a/src/prolog/lib/time.pl +++ b/src/prolog/lib/time.pl @@ -13,13 +13,14 @@ :- use_module(library(format)). :- use_module(library(iso_ext)). +:- use_module(library(error)). max_sleep_time(0xfffffffffffffbff). sleep(T) :- builtins:must_be_number(T, sleep), ( T < 0 -> - throw(error(domain_error(not_less_than_zero, T), sleep/1)) + domain_error(not_less_than_zero, T, sleep/1) ; max_sleep_time(N), T > N -> throw(error(reprensentation_error(max_sleep_time), sleep/1)) ; '$sleep'(T) From ff41d6aef91830a3b98997d937412ec6cbea7f33 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 17:56:46 +0200 Subject: [PATCH 4/6] include the new library(random) in the overview Many thanks to @notoria for this contribution! --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c1e40c59..f0d0b6ac 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,8 @@ The modules that ship with Scryer Prolog are also called for measuring the performance of your code. * [`cont`](src/prolog/lib/cont.pl) Provides *delimited continuations* via `reset/3` and `shift/1`. +* [`random`](src/prolog/lib/random.pl) + Probabilistic predicates and random number generators. To read contents of external files, use `phrase_from_file/2` from [`library(pio)`](src/prolog/lib/pio.pl) to apply a DCG to From 89a4b5a6ffc74831a76429ab4afec8d0da7db7e7 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 19:48:31 +0200 Subject: [PATCH 5/6] add more information about Constraint Logic Programming (CLP) --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index f0d0b6ac..202a5b42 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,24 @@ described in [*Tabling as a Library with Delimited Control*](https://biblio.ugent.be/publication/6880648/file/6885145.pdf) by Desouter et. al. +### Constraint Logic Programming (CLP) + +Scryer Prolog provides excellent support for Constraint Logic +Programming (CLP), which is the amalgamation of +Logic Programming (LP) and Constraints. + +In addition to built-in support for [`dif/2`](src/prolog/lib/dif.pl), +[`freeze/2`](src/prolog/lib/freeze.pl), +[CLP(ℤ)](src/prolog/lib/clpz.pl) and [CLP(B)](src/prolog/lib/clpb.pl), +Scryer provides a convenient way to implement new user-defined +constraints: *Attributed variables* are available via +[`library(atts)`](src/prolog/lib/atts.pl) as in SICStus Prolog, +which is one of the most sophisticated and fastest constraint systems +in existence. + +These features make Scryer Prolog an ideal platform for teaching, +learning and developing portable CLP applications. + ### Modules Scryer has a simple predicate-based module system. It provides a From 5f35dffa34387cc48d23f128a0e90bc627cc24b3 Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Mon, 27 Apr 2020 19:53:25 +0200 Subject: [PATCH 6/6] `if_` --> `if_/3` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 202a5b42..e30bd1b7 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Extend Scryer Prolog to include the following, among other features: - [x] Support for `verify_attributes/3` - [x] Support for `attribute_goals/2` and `project_attributes/2` - [x] `call_residue_vars/2` -- [x] `if_` and related predicates, following the developments of the +- [x] `if_/3` and related predicates, following the developments of the paper "Indexing `dif/2`". - [x] All-solutions predicates (`findall/{3,4}`, `bagof/3`, `setof/3`, `forall/2`). - [x] Clause creation and destruction (`asserta/1`, `assertz/1`,