eyeprolog 1.3.76 → 1.3.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/examples/binomial-vandermonde.pl +1 -1
- package/examples/book/chapter-26/02-triple.pl +1 -1
- package/examples/book/chapter-28/02-triangle.pl +1 -1
- package/examples/book/chapter-28/04-integer_rectangle.pl +1 -1
- package/examples/book/chapter-29/01-counterexample_to_odd_square.pl +1 -1
- package/examples/book/chapter-31/03-double.pl +1 -1
- package/examples/book/chapter-32/04-reference_square.pl +1 -1
- package/examples/book/chapter-33/03-chosen_pair.pl +1 -1
- package/examples/book/chapter-39/01-answer.pl +1 -1
- package/examples/catalan-convolution.pl +1 -1
- package/examples/collatz-1000.pl +1 -1
- package/examples/continued-fraction-sqrt2.pl +1 -1
- package/examples/easter-computus.pl +1 -1
- package/examples/equality-saturation.pl +1 -1
- package/examples/goldbach.pl +1 -1
- package/examples/integer-partitions.pl +1 -1
- package/examples/job-shop-scheduling.pl +1 -1
- package/examples/matrix-chain-order.pl +1 -1
- package/examples/missionaries-cannibals.pl +1 -1
- package/examples/pell-equation.pl +1 -1
- package/examples/polynomial.pl +1 -1
- package/examples/prime-range.pl +1 -1
- package/examples/stirling-bell-numbers.pl +1 -1
- package/examples/totient-summatory.pl +1 -1
- package/package.json +1 -1
- package/src/iso.js +74 -25
- package/src/lib/lists.pl +15 -5
- package/src/lib/prologue.pl +30 -166
- package/src/program.js +20 -8
- package/src/quads.js +24 -3
- package/src/repl.js +4 -2
- package/src/solver.js +75 -24
- package/src/standard-library.js +5 -6
- package/test/fixtures/README.md +8 -0
- package/test/fixtures/variable_names_quad.pl +163 -0
- package/test/run-regression.mjs +106 -6
- package/test/test-support.mjs +1 -1
- package/the-art-of-eyeprolog.md +30 -23
package/test/run-regression.mjs
CHANGED
|
@@ -1565,6 +1565,18 @@ c4 ?- call((!;1)).
|
|
|
1565
1565
|
assertEqual(result.stderr, '', 'quad stderr');
|
|
1566
1566
|
},
|
|
1567
1567
|
},
|
|
1568
|
+
{
|
|
1569
|
+
name: 'CLI passes the complete authoritative variable_names quad corpus (issue #69)',
|
|
1570
|
+
run: () => {
|
|
1571
|
+
const filename = path.join(testRoot, 'fixtures', 'variable_names_quad.pl');
|
|
1572
|
+
const source = fs.readFileSync(filename, 'utf8');
|
|
1573
|
+
assertEqual(Program.parse(source).quads.length, 74, 'vendored query-record total');
|
|
1574
|
+
const result = runCli(['-q', filename], { cwd: tmp });
|
|
1575
|
+
assertEqual(result.status, 0, 'quad exit status');
|
|
1576
|
+
assertEqual(result.stdout, 'quads: 75 run, 75 passed, 0 failed.\n', 'quad report');
|
|
1577
|
+
assertEqual(result.stderr, '', 'quad stderr');
|
|
1578
|
+
},
|
|
1579
|
+
},
|
|
1568
1580
|
{
|
|
1569
1581
|
name: 'REPL advances anonymous Prologue length checks through I = 28',
|
|
1570
1582
|
run: () => {
|
|
@@ -1814,6 +1826,41 @@ c4 ?- call((!;1)).
|
|
|
1814
1826
|
assertEqual(result.stderr, '', 'stderr');
|
|
1815
1827
|
},
|
|
1816
1828
|
},
|
|
1829
|
+
{
|
|
1830
|
+
name: 'REPL omits exhausted choicepoints without probing future branches (issue #74)',
|
|
1831
|
+
run: () => {
|
|
1832
|
+
const result = runCli([], {
|
|
1833
|
+
input:
|
|
1834
|
+
'X=1;X=2.\n;\n' +
|
|
1835
|
+
'setof(X,true,Xs).\n' +
|
|
1836
|
+
'findall(t,false,Xs).\n' +
|
|
1837
|
+
'use_module(library(lists)).\n' +
|
|
1838
|
+
'member(a,"ba").\n' +
|
|
1839
|
+
'append("a",Xs,Xs0).\n' +
|
|
1840
|
+
'halt.\n',
|
|
1841
|
+
});
|
|
1842
|
+
assertEqual(result.status, 0, 'exit status');
|
|
1843
|
+
assertEqual(result.stdout,
|
|
1844
|
+
'?- X = 1\n' +
|
|
1845
|
+
'; X = 2.\n' +
|
|
1846
|
+
'?- Xs = [_A].\n' +
|
|
1847
|
+
'?- Xs = [].\n' +
|
|
1848
|
+
'?- true.\n' +
|
|
1849
|
+
'?- true.\n' +
|
|
1850
|
+
'?- Xs0 = [a | Xs].\n' +
|
|
1851
|
+
'?- ',
|
|
1852
|
+
'stdout');
|
|
1853
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
1854
|
+
|
|
1855
|
+
const grouped = new Solver(Program.parse(''));
|
|
1856
|
+
const groupedSolutions = grouped.solve([
|
|
1857
|
+
parseGoalText('setof(X,(Y=1,X=a;Y=2,X=b),Xs)'),
|
|
1858
|
+
], new Env(), 0);
|
|
1859
|
+
assertEqual(groupedSolutions.next().done, false, 'first grouped setof/3 answer');
|
|
1860
|
+
assertEqual(grouped.hasPendingAlternatives(), true, 'genuine grouped setof/3 choicepoint');
|
|
1861
|
+
groupedSolutions.return();
|
|
1862
|
+
},
|
|
1863
|
+
},
|
|
1817
1864
|
{
|
|
1818
1865
|
name: 'REPL hides aliases to fresh throw variables while preserving query aliases',
|
|
1819
1866
|
run: () => {
|
|
@@ -1825,6 +1872,15 @@ c4 ?- call((!;1)).
|
|
|
1825
1872
|
assertEqual(result.stderr, '', 'stderr');
|
|
1826
1873
|
},
|
|
1827
1874
|
},
|
|
1875
|
+
{
|
|
1876
|
+
name: 'REPL displays uncaught user exceptions as throw terms (issue #75)',
|
|
1877
|
+
run: () => {
|
|
1878
|
+
const result = runCli([], { input: 'throw(stopped).\nhalt.\n' });
|
|
1879
|
+
assertEqual(result.status, 0, 'exit status');
|
|
1880
|
+
assertEqual(result.stdout, '?- throw(stopped).\n?- ', 'stdout');
|
|
1881
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
1882
|
+
},
|
|
1883
|
+
},
|
|
1828
1884
|
{
|
|
1829
1885
|
name: 'REPL freshens variables displayed in uncaught ISO errors',
|
|
1830
1886
|
run: () => {
|
|
@@ -2830,6 +2886,22 @@ child.stdin.write(\`consult(${consultedAtom}).\\n\`);
|
|
|
2830
2886
|
assertEqual(result.stderr, '', 'stderr');
|
|
2831
2887
|
},
|
|
2832
2888
|
},
|
|
2889
|
+
{
|
|
2890
|
+
name: 'REPL combines canonical libraries with the Prologue facade',
|
|
2891
|
+
run: () => {
|
|
2892
|
+
const result = runCli([], {
|
|
2893
|
+
input:
|
|
2894
|
+
'use_module(library(freeze)).\n' +
|
|
2895
|
+
'use_module(library(lists)).\n' +
|
|
2896
|
+
'use_module(library(iso_ext)).\n' +
|
|
2897
|
+
'use_module(library(prologue)).\n' +
|
|
2898
|
+
'halt.\n',
|
|
2899
|
+
});
|
|
2900
|
+
assertEqual(result.status, 0, 'exit status');
|
|
2901
|
+
assertEqual(result.stdout, '?- true.\n?- true.\n?- true.\n?- true.\n?- ', 'stdout');
|
|
2902
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
2903
|
+
},
|
|
2904
|
+
},
|
|
2833
2905
|
{
|
|
2834
2906
|
name: 'REPL halt status is returned by the CLI',
|
|
2835
2907
|
run: () => {
|
|
@@ -4566,7 +4638,7 @@ answer(ok) :-
|
|
|
4566
4638
|
const program = Program.parse('answer(X) :- member(X, [a]), between(1, 1, _).\n');
|
|
4567
4639
|
assertEqual(program.autoloadedPredicates.length, 2, 'autoloaded predicate count');
|
|
4568
4640
|
assertEqual(program.autoloadedPredicates.map((entry) => `${entry.indicator}:${entry.library}`).sort().join(','),
|
|
4569
|
-
'between/3:
|
|
4641
|
+
'between/3:between,member/2:lists', 'autoload mapping');
|
|
4570
4642
|
assertEqual(program.interopPortabilityWarnings.length, 0, 'autoloaded portable calls are warning-free');
|
|
4571
4643
|
},
|
|
4572
4644
|
},
|
|
@@ -5050,9 +5122,9 @@ answer(ok) :-
|
|
|
5050
5122
|
assertEqual(registeredNativeEyePrologLibraryNames().length, 49, 'public native EyeProlog builtin count');
|
|
5051
5123
|
assertEqual(eyePrologPortableLibraryIndicators.length, 87, 'portable Prolog library count');
|
|
5052
5124
|
assertEqual(eyePrologInteropLibraryIndicators.length, 30, 'cross-implementation interop profile count');
|
|
5053
|
-
assertEqual(eyePrologInteropLibraryModules.join(','), 'lists,iso_ext,lambda,atts', 'common explicit library module profile');
|
|
5125
|
+
assertEqual(eyePrologInteropLibraryModules.join(','), 'lists,iso_ext,lambda,atts,freeze', 'common explicit library module profile');
|
|
5054
5126
|
assertEqual(eyePrologInteropAutoload['member/2'], 'lists', 'member/2 canonical autoload');
|
|
5055
|
-
assertEqual(eyePrologInteropAutoload['between/3'], '
|
|
5127
|
+
assertEqual(eyePrologInteropAutoload['between/3'], 'between', 'between/3 canonical internal autoload');
|
|
5056
5128
|
assertEqual(eyePrologInteropAutoload['call_nth/2'], 'iso_ext', 'call_nth/2 canonical interop autoload');
|
|
5057
5129
|
assertEqual(eyePrologInteropAutoload['call_residue_vars/2'], 'atts', 'call_residue_vars/2 canonical interop autoload');
|
|
5058
5130
|
assertEqual(eyePrologInteropAutoload['time/1'], 'iso_ext', 'time/1 canonical interop autoload');
|
|
@@ -5113,13 +5185,41 @@ answer(ok) :-
|
|
|
5113
5185
|
assertEqual(program.findGroup('random', 3)?.module, 'random', 'random/3 is imported from library(random)');
|
|
5114
5186
|
},
|
|
5115
5187
|
},
|
|
5188
|
+
{
|
|
5189
|
+
name: 'Prologue facade re-exports canonical library predicates without conflicts',
|
|
5190
|
+
run: () => {
|
|
5191
|
+
const sources = [
|
|
5192
|
+
':- use_module(library(freeze)).\n:- use_module(library(lists)).\n:- use_module(library(iso_ext)).\n:- use_module(library(prologue)).',
|
|
5193
|
+
':- use_module(library(prologue)).\n:- use_module(library(freeze)).\n:- use_module(library(lists)).\n:- use_module(library(iso_ext)).',
|
|
5194
|
+
];
|
|
5195
|
+
for (const source of sources) {
|
|
5196
|
+
const program = Program.parse(source);
|
|
5197
|
+
assertEqual(program.findGroup('freeze', 2)?.module, 'freeze', 'freeze/2 canonical owner');
|
|
5198
|
+
assertEqual(program.findGroup('member', 2)?.module, 'lists', 'member/2 canonical owner');
|
|
5199
|
+
assertEqual(program.findGroup('call_nth', 2)?.module, 'iso_ext', 'call_nth/2 canonical owner');
|
|
5200
|
+
assertEqual(program.findGroup('between', 3)?.module, 'between', 'between/3 canonical owner');
|
|
5201
|
+
}
|
|
5202
|
+
|
|
5203
|
+
const conflicting = new Program();
|
|
5204
|
+
conflicting.defineModule('first', [{ name: 'shared', arity: 1 }]);
|
|
5205
|
+
conflicting.defineModule('second', [{ name: 'shared', arity: 1 }]);
|
|
5206
|
+
conflicting.importModule('user', 'first');
|
|
5207
|
+
let conflict = null;
|
|
5208
|
+
try {
|
|
5209
|
+
conflicting.importModule('user', 'second');
|
|
5210
|
+
} catch (error) {
|
|
5211
|
+
conflict = error;
|
|
5212
|
+
}
|
|
5213
|
+
assertEqual(conflict?.formal, 'permission_error(import, procedure)', 'distinct implementations still conflict');
|
|
5214
|
+
},
|
|
5215
|
+
},
|
|
5116
5216
|
{
|
|
5117
5217
|
name: 'aligned bundled libraries have no overlapping full-module exports',
|
|
5118
5218
|
run: () => {
|
|
5119
5219
|
const owners = new Map();
|
|
5120
5220
|
for (const [moduleName, entry] of standardLibrarySources) {
|
|
5121
|
-
// library(prologue) is
|
|
5122
|
-
//
|
|
5221
|
+
// library(prologue) is a facade whose nominal exports are re-exports;
|
|
5222
|
+
// canonical libraries must remain pairwise collision-free so full
|
|
5123
5223
|
// use_module/1 imports can be combined safely.
|
|
5124
5224
|
if (moduleName === 'prologue') continue;
|
|
5125
5225
|
const parsed = Program.parse(entry.source);
|
|
@@ -6541,7 +6641,7 @@ child.on('close', (status, signal) => {
|
|
|
6541
6641
|
|
|
6542
6642
|
function runCli(args, options = {}) {
|
|
6543
6643
|
return spawnSync(process.execPath, [bin, ...args], {
|
|
6544
|
-
cwd: packageRoot,
|
|
6644
|
+
cwd: options.cwd ?? packageRoot,
|
|
6545
6645
|
encoding: 'utf8',
|
|
6546
6646
|
env: options.env ? { ...process.env, ...options.env } : process.env,
|
|
6547
6647
|
input: options.input ?? undefined,
|
package/test/test-support.mjs
CHANGED
|
@@ -10,7 +10,7 @@ const standardModulePrelude = `:- use_module(library(aggregate)).
|
|
|
10
10
|
:- use_module(library(iso_ext)).
|
|
11
11
|
:- use_module(library(lists)).
|
|
12
12
|
:- use_module(library(primes)).
|
|
13
|
-
:- use_module(library(
|
|
13
|
+
:- use_module(library(between), [between/3]).
|
|
14
14
|
:- use_module(library(random)).
|
|
15
15
|
:- use_module(library(strings)).
|
|
16
16
|
:- use_module(library(uuid)).
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -3568,7 +3568,7 @@ methods.
|
|
|
3568
3568
|
Consider a relation for a Pythagorean triple:
|
|
3569
3569
|
|
|
3570
3570
|
```eyeprolog
|
|
3571
|
-
:- use_module(library(
|
|
3571
|
+
:- use_module(library(between), [between/3]).
|
|
3572
3572
|
:- use_module(library(lists)).
|
|
3573
3573
|
|
|
3574
3574
|
triple(A, B, C) :-
|
|
@@ -3880,7 +3880,7 @@ permutations repeats the same geometric object six times. Ordering the sides
|
|
|
3880
3880
|
removes the symmetry:
|
|
3881
3881
|
|
|
3882
3882
|
```eyeprolog
|
|
3883
|
-
:- use_module(library(
|
|
3883
|
+
:- use_module(library(between), [between/3]).
|
|
3884
3884
|
:- use_module(library(lists)).
|
|
3885
3885
|
|
|
3886
3886
|
triangle(A, B, C) :-
|
|
@@ -3918,7 +3918,7 @@ it from width and height. With a finite generator it can also search for
|
|
|
3918
3918
|
factorizations:
|
|
3919
3919
|
|
|
3920
3920
|
```eyeprolog
|
|
3921
|
-
:- use_module(library(
|
|
3921
|
+
:- use_module(library(between), [between/3]).
|
|
3922
3922
|
:- use_module(library(lists)).
|
|
3923
3923
|
|
|
3924
3924
|
integer_rectangle(Area, W, H) :-
|
|
@@ -4031,7 +4031,7 @@ theorem over an unbounded domain.
|
|
|
4031
4031
|
This boundary can be written directly:
|
|
4032
4032
|
|
|
4033
4033
|
```eyeprolog
|
|
4034
|
-
:- use_module(library(
|
|
4034
|
+
:- use_module(library(between), [between/3]).
|
|
4035
4035
|
:- use_module(library(lists)).
|
|
4036
4036
|
|
|
4037
4037
|
counterexample_to_odd_square(N) :-
|
|
@@ -4470,7 +4470,7 @@ Examples test selected points. A finite generated property tests every point
|
|
|
4470
4470
|
in a declared scope:
|
|
4471
4471
|
|
|
4472
4472
|
```eyeprolog
|
|
4473
|
-
:- use_module(library(
|
|
4473
|
+
:- use_module(library(between), [between/3]).
|
|
4474
4474
|
:- use_module(library(lists)).
|
|
4475
4475
|
|
|
4476
4476
|
double(N, D) :- (D is N + N).
|
|
@@ -4724,7 +4724,7 @@ compare it with the optimized one. The reference may be slow; its purpose is
|
|
|
4724
4724
|
clarity.
|
|
4725
4725
|
|
|
4726
4726
|
```eyeprolog
|
|
4727
|
-
:- use_module(library(
|
|
4727
|
+
:- use_module(library(between), [between/3]).
|
|
4728
4728
|
:- use_module(library(lists)).
|
|
4729
4729
|
|
|
4730
4730
|
reference_square(N, S) :-
|
|
@@ -4865,7 +4865,7 @@ explanation until none can be reasoned about separately.
|
|
|
4865
4865
|
in dependency order, then construct a witness or reason.
|
|
4866
4866
|
|
|
4867
4867
|
```eyeprolog
|
|
4868
|
-
:- use_module(library(
|
|
4868
|
+
:- use_module(library(between), [between/3]).
|
|
4869
4869
|
:- use_module(library(lists)).
|
|
4870
4870
|
|
|
4871
4871
|
chosen_pair(pair(X, Y), reason(sum_is_ten)) :-
|
|
@@ -6222,17 +6222,23 @@ clauses over private adapters. `time/1` is additionally registered directly in
|
|
|
6222
6222
|
the normal EyeProlog runtime so Trealla-style timing works at the interactive
|
|
6223
6223
|
top level without an import; it is absent from the strict ISO registry.
|
|
6224
6224
|
|
|
6225
|
-
The sources are `src/lib/aggregate.pl`, `src/lib/
|
|
6226
|
-
`src/lib/
|
|
6227
|
-
`src/lib/
|
|
6228
|
-
`src/lib/
|
|
6225
|
+
The sources are `src/lib/aggregate.pl`, `src/lib/arithmetic.pl`,
|
|
6226
|
+
`src/lib/assoc.pl`, `src/lib/atts.pl`, `src/lib/between.pl`,
|
|
6227
|
+
`src/lib/clpz.pl`, `src/lib/comparison.pl`, `src/lib/dates.pl`,
|
|
6228
|
+
`src/lib/dcgs.pl`, `src/lib/debug.pl`, `src/lib/error.pl`,
|
|
6229
|
+
`src/lib/format.pl`, `src/lib/freeze.pl`, `src/lib/iso_ext.pl`,
|
|
6230
|
+
`src/lib/lambda.pl`, `src/lib/lists.pl`, `src/lib/pairs.pl`,
|
|
6231
|
+
`src/lib/primes.pl`, `src/lib/prologue.pl`, `src/lib/random.pl`,
|
|
6232
|
+
`src/lib/si.pl`, `src/lib/strings.pl`, `src/lib/terms.pl`, and
|
|
6233
|
+
`src/lib/uuid.pl`. Each declares a same-named module
|
|
6229
6234
|
with `module/2`; there is no catch-all `library(eyeprolog)`. A program imports
|
|
6230
6235
|
only the modules it needs, and
|
|
6231
6236
|
`use_module/2` can select an even smaller indicator list. The Prologue
|
|
6232
|
-
module
|
|
6237
|
+
module exposes p.p.1 through p.p.11 of the
|
|
6233
6238
|
[working-draft Prologue](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue),
|
|
6234
|
-
|
|
6235
|
-
|
|
6239
|
+
as a compatibility facade over the canonical `lists`, `between`, `iso_ext`,
|
|
6240
|
+
and `freeze` modules. The published Prologue, `call_nth/2`, and `length/2`
|
|
6241
|
+
quads are retained as offline regressions. `src/standard-library.js` registers the module sources and private control and
|
|
6236
6242
|
constraint adapters for Node and browser resolution. Explicit `use_module/1-2`
|
|
6237
6243
|
loads remain supported; outside strict ISO mode, the conservative interop
|
|
6238
6244
|
autoloader may also load a module for one uniquely mapped common predicate.
|
|
@@ -6294,7 +6300,9 @@ The current interoperability profile recognizes these library roles:
|
|
|
6294
6300
|
| `library(lists)` | Common list module. A conservative subset of its exports is in the shared predicate profile. |
|
|
6295
6301
|
| `library(iso_ext)` | Common extension-module name. `call_nth/2`, `time/1`, and the `... //0` arbitrary-sequence helper are conservatively autoloaded for cross-engine source. |
|
|
6296
6302
|
| `library(lambda)` | Scryer-aligned higher-order notation. It is imported explicitly because loading it also installs the `+\` operator. |
|
|
6297
|
-
| `library(
|
|
6303
|
+
| `library(atts)` | Common attributed-variable interface used by constraint libraries. |
|
|
6304
|
+
| `library(freeze)` | Common delayed-goal module backed by attributed variables. |
|
|
6305
|
+
| `library(prologue)` | EyeProlog compatibility facade, not a common interop library name. Its exports resolve to canonical focused modules instead of duplicate implementations. |
|
|
6298
6306
|
|
|
6299
6307
|
Other modules from the catalog, including `library(clpz)`, `library(strings)`,
|
|
6300
6308
|
`library(random)`, and `library(uuid)`, remain normal EyeProlog libraries. They
|
|
@@ -6323,11 +6331,10 @@ for example `% Time elapsed 0.832s, 65551 Inferences, 0.079 MLips`; `... //0`
|
|
|
6323
6331
|
describes an arbitrary number of input elements. Together they let the
|
|
6324
6332
|
Trealla/Scryer DCG hand-off benchmark run in EyeProlog without source changes
|
|
6325
6333
|
(assuming the usual list library is already imported in an interactive
|
|
6326
|
-
session). The
|
|
6327
|
-
`library(
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
with the aligned modules.
|
|
6334
|
+
session). The focused modules have one canonical implementation owner per
|
|
6335
|
+
predicate. `library(prologue)` re-exports those same owners, so legacy code can
|
|
6336
|
+
combine the facade with `library(lists)`, `library(iso_ext)`, and
|
|
6337
|
+
`library(freeze)` in either import order without an accidental collision.
|
|
6331
6338
|
|
|
6332
6339
|
`library(lambda)` follows Scryer's higher-order notation, adapted from Ulrich
|
|
6333
6340
|
Neumerkel's permissively licensed implementation. Its public syntax is:
|
|
@@ -6372,7 +6379,7 @@ extension. For example, the canonical build-time providers are:
|
|
|
6372
6379
|
| `call_nth/2` | `library(iso_ext)` |
|
|
6373
6380
|
| `time/1` | `library(iso_ext)` |
|
|
6374
6381
|
| `.../2` | `library(iso_ext)` |
|
|
6375
|
-
| `between/3` | `library(
|
|
6382
|
+
| `between/3` | `library(between)` |
|
|
6376
6383
|
|
|
6377
6384
|
Predicates outside that table require an explicit import even when EyeProlog
|
|
6378
6385
|
provides them. Explicit imports therefore remain the clearest way to state
|
|
@@ -6494,7 +6501,7 @@ before calling the corresponding predicate.
|
|
|
6494
6501
|
|
|
6495
6502
|
```eyeprolog
|
|
6496
6503
|
:- use_module(library(dates)).
|
|
6497
|
-
:- use_module(library(
|
|
6504
|
+
:- use_module(library(between), [between/3]).
|
|
6498
6505
|
:- use_module(library(random)).
|
|
6499
6506
|
:- use_module(library(lists)).
|
|
6500
6507
|
|
|
@@ -6515,7 +6522,7 @@ expresses them: for example, `R is A + B`, `R is abs(A)`, and
|
|
|
6515
6522
|
modulo, powers, sine, cosine, exponential, logarithm, and the ISO rounding
|
|
6516
6523
|
functions.
|
|
6517
6524
|
|
|
6518
|
-
The bundled library layer defines `between/3` in `library(
|
|
6525
|
+
The bundled library layer defines `between/3` in `library(between)` and
|
|
6519
6526
|
`smallest_divisor_from/3` in `library(primes)` as ordinary Prolog clauses.
|
|
6520
6527
|
Choose the smaller or
|
|
6521
6528
|
larger of two arithmetic values directly with ISO control, for example
|