This issue was found by @david-sitsky in a Prolog formulation of an
interesting scheduling task:
https://github.com/mthom/scryer-prolog/discussions/3341
See also the filed issue:
https://github.com/mthom/scryer-prolog/issues/3369
Thank you a lot!
This issue needs more analysis to find out what exactly happened here,
whether other cases like it exist, and whether it can be addressed in
a better way. I would greatly appreciate any help!
Quoting from the standard:
7.4.2.7 include/1
If F is an implementation defined ground term designating
a Prolog text unit, then Prolog text P1 which contains
a directive include(F) is identical to a Prolog text P2
obtained by replacing the directive include(F) in P1 by
the Prolog text denoted by F.
Example:
:- include("hello.pl").
This addresses #583 and #634.
This lets us embed toplevel interactions in Prolog programs.
Embedded toplevel interactions are currently ignored.
Example:
:- use_module(library(lists)).
?- member(X, "abc").
X = a
; X = b
; X = c.
This address #2924, reported by @haijinSk. Thank you a lot!
Example:
?- arg(2, "a", A).
A = [].
The fact that such a mistake in macro usage is even possible could be
a sign that the macro definition should be stricter.
Suggested by Oleg Finkelstein, thank you a lot!
Example, before this change:
?- t+\(length(As, 1_000_000), maplist(=(a), As), time(atom_chars(A, As))).
% CPU time: 0.693s, 7_000_041 inferences
true.
Now:
?- t+\(length(As, 1_000_000), maplist(=(a), As), time(atom_chars(A, As))).
% CPU time: 0.080s, 40 inferences
true.
This also partially ameliorates #2907.
rebis-dev makes the speed difference especially apparent due to the
linear scan of strings on the heap in partial_string_tail/2 which is
now avoided for repositionable streams, notably files.
This addresses #2888 reported and analyzed by @haijinSk. Many thanks!
This addresses #2771. Many thanks to @tmerr for reporting the issue!
The code was posted by @UWN in:
https://github.com/mthom/scryer-prolog/discussions/2805
Many thanks! With additional inputs by @adri326 and @notoria, who also
posted interesting approaches which could help to increase precision
in cases that are currently not ideally handled. Thank you all!
Please see the issue and discussion for more information.
"returns" is not used in this way in logic programming. "return"
suggests that something went away and is now coming back, but this is
never the case in these situations. The arguments may be variables or
also fully known at the time of the call in most cases.
Examples:
?- portray_clause(((+) :- a=b,(-))).
(+) :-
a=b,
(-).
true.
?- portray_clause((a :- (b :- c))).
a :-
(b:-c).
true.
This addresses #2715.
Currently, more round brackets than needed are emitted. Ideally, a
better approach to solve the issue here and also in toplevel.pl is
found in the future.
This addresses #2713. Many thanks to @notoria for reporting this
excellent case!
Example:
?- portray_clause(A = @).
A= @ .
true.
At other positions the now inserted space is unnecessary, as in:
?- portray_clause((head:- @,b)).
head :-
@ ,
b.
true.
The toplevel has a similar issue:
?- C = # ; false.
C = # |<-- cursor is here; redundant space after #
There may be a way to solve this issue for all cases like this.
Many thanks to @hurufu for the very nice definition!
This is until library(random) provides this functionality,
and a good name is found for it. See #2670.
This usage is now considered deprecated. Use strings instead for
greater efficiency and type consistency in your applications.
This functionality is a candidate for removal in a future commit.
In particular, octet does *not* mean that the input is a list of
Prolog bytes in the sense of "integers between 0..255", but that the
character codes are used directly as byte values.
These non-terminals take a grammar rule body and additional arguments
as arguments. These arguments are appended to the first argument.
A key motivation for the introduction of these non-terminals is found
in the discussion and sample code provided by @bakaq in:
https://github.com/mthom/scryer-prolog/discussions/2260
In this way, portable higher-order DCG programming is possible while
keeping the logical grammar rule expansion implementation dependent.
Example:
?- phrase(phrase('.', a, []), Cs).
Cs = "a".
This allows subsequently invoked constraints to take the entire
filtering results into account, instead of being invoked when the
obtained information is not yet entirely used.
The SICStus-style attributed variables mechanism of Scryer Prolog
automatically prevents very subtle interaction problems that can arise
in systems that do not give all variables that are involved in a
unification an opportunity to schedule their propagators.
An example of such a subtle interaction is:
?- tuples_in([[A,C,B]], [[3,1,3],[4,2,4]]),
global_cardinality([A,B,D], [3-1,4-2]),
A = 4.
A = 4 causes pgcc_check/1 and pgcc/2 to be queued in the fast and slow
queue, respectively. In the fast queue, there is also rel_tuple/2,
which is worked off after gcc_check/1 and simultaneously instantiates
both C and B (to 2 and 4, respectively). Instantiation of C schedules
do_queue//0 from verify_attributes/3. Note that C does not participate
in the global_cardinality/2 constraint.
Critically, B also gets an opportunity to schedule its propagators in
this case, so another gcc_check/1 is run before gcc_global/2!
This allows subsequently invoked constraints to take the entire
filtering results into account, instead of being invoked when the
obtained information is not yet entirely used.
It speeds up programs such as the one in:
https://github.com/triska/clpz/issues/26
The main motivation for this change is the introduction of the newly
available predicate ed25519_seed_keypair/2, allowing to generate a key
pair from a given seed. In this way, a key pair can be dynamically
generated from (for example) a password, using crypto_password_hash/3
in combination with crypto_data_hkdf/4 to generate the seed. The
advantage of this method is that the private key need not be stored at
all anywhere.
It is not possible to add a corresponding feature to ring, since it is
closed as "not planned": https://github.com/briansmith/ring/issues/1003
I also used this opportunity to move more of the logic to Prolog. We
now have total control of the key pair representation, and I also
changed the representation to conform to the PKCS#8 v2 standard,
something that only later ring versions do, while still being
backwards compatible with tools that produce a wrong representation
including earlier ring versions.
Another great advantage we get from this change is that the Ed25519
predicates now also run on the 32-bit and WASM versions of Scryer.
One use case is to ensure that once/1 is safe to use:
term_si(Goal),
once(Goal)
In such cases, Goal is ground and can yield at most one solution,
therefore once/1 does not remove any solutions.
Example:
?- time(member(X, "abc")).
% CPU time: 0.000s, 1 inference
X = a
; % CPU time: 0.000s, 3 inferences
X = b
; % CPU time: 0.000s, 3 inferences
X = c.
This is an initial step towards addressing #1039.
If reification constraints (such as reified equality) are triggered
here, then they may wish to disable this propagator and remove
attributes from auxiliary variables. If the pexp/3 propagation is
interrupted for that purpose, then the attributes will be
unintentionally reattached by the following fd_put/3 calls in this
propagator. We must ensure that this propagator completely finishes,
so we queue the triggered propagators for later processing.
geq/2 implements propagator activation outside the queue, and thus
should not be used in propagators in the way it was used here.
pexp/3 by itself may not seem particularly important. However, it can
arise by metamorphosis from Var*Var. Example:
?- A#<==> -1#=C*C, C in 0..1.
A = 0, clpz:(C in 0..1).
This addresses #2089.
This addresses all remaining cases from #2083, excepting (//)/2:
?- #\ 1#=(X*X)/0.
clpz:(X in inf..sup).
?- #\ 1#=(X+X)/0.
clpz:(X in inf..sup).
Still remaining:
?- #\ 0#=(Y// -1)/0.
clpz:(-1*Y#=_A).