eyeprolog 1.3.7 → 1.3.8

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 CHANGED
@@ -189,12 +189,13 @@ noun --> [world] | [prolog].
189
189
  %% goal: phrase(sentence, Words)
190
190
  ```
191
191
 
192
- EyeProlog also adds 102 public library predicate indicators to its 129-entry ISO
193
- profile. **63 are implemented entirely as ordinary Prolog clauses** in focused
194
- modules under `src/lib/`; the control predicates and finite-domain
192
+ EyeProlog also adds 126 public library predicate indicators to its 129-entry ISO
193
+ profile. **87 are implemented entirely as ordinary Prolog clauses** in focused
194
+ modules under `src/lib/`; the remaining control predicates and finite-domain
195
195
  `library(clpz)` kernel use backtrackable host support.
196
196
  They are ISO/IEC 13211-2 modules loaded explicitly by purpose, such as
197
- `library(lists)`, `library(strings)`, `library(aggregate)`, or `library(clpz)`.
197
+ `library(lists)`, `library(lambda)`, `library(strings)`, `library(aggregate)`, or
198
+ `library(clpz)`.
198
199
  Portable text
199
200
  predicates use ISO atoms or character lists. The old catch-all
200
201
  `library(eyeprolog)` module is no longer needed.
@@ -217,6 +218,24 @@ they can be imported together without an accidental import conflict. EyeProlog's
217
218
  legacy `library(prologue)` remains a compatibility umbrella and should be
218
219
  selectively imported when mixed with the aligned modules.
219
220
 
221
+ `library(lambda)` follows Scryer's higher-order lambda notation, adapted from
222
+ Ulrich Neumerkel's permissively licensed implementation. Importing it installs
223
+ the `+\` operator and enables closures such as `\X^Goal` and
224
+ `Free+\X^Goal`. Parameters are supplied by `call/N`; variables not listed in
225
+ `Free` are copied afresh for each invocation, while explicitly free variables
226
+ remain shared. For example:
227
+
228
+ ```prolog
229
+ :- use_module(library(lambda)).
230
+ :- use_module(library(lists)).
231
+
232
+ all_positive(Xs) :- maplist(\X^(X > 0), Xs).
233
+ all_equal(Y, Xs) :- maplist(Y+\X^(X = Y), Xs).
234
+ ```
235
+
236
+ The explicit import is intentional: unlike ordinary predicate autoloading, the
237
+ lambda syntax also changes the active operator table.
238
+
220
239
  Outside `--iso-strict`, an otherwise undefined unqualified call may autoload a
221
240
  predicate only when the interop profile has one canonical EyeProlog provider.
222
241
  For example, `member/2` autoloads from `library(lists)`, `call_nth/2` from
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.3.7",
6
+ "version": "1.3.8",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
@@ -0,0 +1,116 @@
1
+ /*
2
+ Author: Ulrich Neumerkel
3
+ E-mail: ulrich@complang.tuwien.ac.at
4
+ Copyright (C): 2009 Ulrich Neumerkel. All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are
8
+ met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY Ulrich Neumerkel ``AS IS'' AND ANY
18
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ulrich Neumerkel OR
21
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ The views and conclusions contained in the software and documentation
30
+ are those of the authors and should not be interpreted as representing
31
+ official policies, either expressed or implied, of Ulrich Neumerkel.
32
+
33
+ Adapted for EyeProlog from Scryer Prolog library(lambda):
34
+ https://github.com/mthom/scryer-prolog/blob/master/src/lib/lambda.pl
35
+ */
36
+
37
+ /** Lambda expressions for higher-order programming based on call/N.
38
+
39
+ Supported forms follow Scryer Prolog library(lambda):
40
+
41
+ Free+\X1^X2^...^XN^Goal
42
+ \X1^X2^...^XN^Goal
43
+
44
+ The second form is shorthand for a lambda with no explicitly shared free
45
+ variables. Variables not listed in Free are copied afresh for each call.
46
+ */
47
+
48
+ :- module(lambda, [
49
+ (^)/3, (^)/4, (^)/5, (^)/6, (^)/7, (^)/8, (^)/9, (^)/10,
50
+ (\)/1, (\)/2, (\)/3, (\)/4, (\)/5, (\)/6, (\)/7, (\)/8,
51
+ (+\)/2, (+\)/3, (+\)/4, (+\)/5, (+\)/6, (+\)/7, (+\)/8, (+\)/9
52
+ ]).
53
+
54
+ % Scryer exports this operator from library(lambda). EyeProlog applies module
55
+ % operator directives while loading the library, so importing the module makes
56
+ % the same syntax available to the importing compilation unit and REPL state.
57
+ :- op(201, xfx, +\).
58
+
59
+ :- meta_predicate(^(?, 0, ?)).
60
+ :- meta_predicate(^(?, 1, ?, ?)).
61
+ :- meta_predicate(^(?, 2, ?, ?, ?)).
62
+ :- meta_predicate(^(?, 3, ?, ?, ?, ?)).
63
+ :- meta_predicate(^(?, 4, ?, ?, ?, ?, ?)).
64
+ :- meta_predicate(^(?, 5, ?, ?, ?, ?, ?, ?)).
65
+ :- meta_predicate(^(?, 6, ?, ?, ?, ?, ?, ?, ?)).
66
+ :- meta_predicate(^(?, 7, ?, ?, ?, ?, ?, ?, ?, ?)).
67
+ :- meta_predicate(\(0)).
68
+ :- meta_predicate(\(1, ?)).
69
+ :- meta_predicate(\(2, ?, ?)).
70
+ :- meta_predicate(\(3, ?, ?, ?)).
71
+ :- meta_predicate(\(4, ?, ?, ?, ?)).
72
+ :- meta_predicate(\(5, ?, ?, ?, ?, ?)).
73
+ :- meta_predicate(\(6, ?, ?, ?, ?, ?, ?)).
74
+ :- meta_predicate(\(7, ?, ?, ?, ?, ?, ?, ?)).
75
+ :- meta_predicate(+\(?, 0)).
76
+ :- meta_predicate(+\(?, 1, ?)).
77
+ :- meta_predicate(+\(?, 2, ?, ?)).
78
+ :- meta_predicate(+\(?, 3, ?, ?, ?)).
79
+ :- meta_predicate(+\(?, 4, ?, ?, ?, ?)).
80
+ :- meta_predicate(+\(?, 5, ?, ?, ?, ?, ?)).
81
+ :- meta_predicate(+\(?, 6, ?, ?, ?, ?, ?, ?)).
82
+ :- meta_predicate(+\(?, 7, ?, ?, ?, ?, ?, ?, ?)).
83
+
84
+ ^(V1, C0, V1) :- lambda__no_hat_call(C0).
85
+ ^(V1, C1, V1, V2) :- call(C1, V2).
86
+ ^(V1, C2, V1, V2, V3) :- call(C2, V2, V3).
87
+ ^(V1, C3, V1, V2, V3, V4) :- call(C3, V2, V3, V4).
88
+ ^(V1, C4, V1, V2, V3, V4, V5) :- call(C4, V2, V3, V4, V5).
89
+ ^(V1, C5, V1, V2, V3, V4, V5, V6) :- call(C5, V2, V3, V4, V5, V6).
90
+ ^(V1, C6, V1, V2, V3, V4, V5, V6, V7) :- call(C6, V2, V3, V4, V5, V6, V7).
91
+ ^(V1, C7, V1, V2, V3, V4, V5, V6, V7, V8) :- call(C7, V2, V3, V4, V5, V6, V7, V8).
92
+
93
+ \(FC0) :- copy_term(FC0, C0), lambda__no_hat_call(C0).
94
+ \(FC1, V1) :- copy_term(FC1, C1), call(C1, V1).
95
+ \(FC2, V1, V2) :- copy_term(FC2, C2), call(C2, V1, V2).
96
+ \(FC3, V1, V2, V3) :- copy_term(FC3, C3), call(C3, V1, V2, V3).
97
+ \(FC4, V1, V2, V3, V4) :- copy_term(FC4, C4), call(C4, V1, V2, V3, V4).
98
+ \(FC5, V1, V2, V3, V4, V5) :- copy_term(FC5, C5), call(C5, V1, V2, V3, V4, V5).
99
+ \(FC6, V1, V2, V3, V4, V5, V6) :- copy_term(FC6, C6), call(C6, V1, V2, V3, V4, V5, V6).
100
+ \(FC7, V1, V2, V3, V4, V5, V6, V7) :- copy_term(FC7, C7), call(C7, V1, V2, V3, V4, V5, V6, V7).
101
+
102
+ +\(GV, FC0) :- copy_term(GV+FC0, GV+C0), lambda__no_hat_call(C0).
103
+ +\(GV, FC1, V1) :- copy_term(GV+FC1, GV+C1), call(C1, V1).
104
+ +\(GV, FC2, V1, V2) :- copy_term(GV+FC2, GV+C2), call(C2, V1, V2).
105
+ +\(GV, FC3, V1, V2, V3) :- copy_term(GV+FC3, GV+C3), call(C3, V1, V2, V3).
106
+ +\(GV, FC4, V1, V2, V3, V4) :- copy_term(GV+FC4, GV+C4), call(C4, V1, V2, V3, V4).
107
+ +\(GV, FC5, V1, V2, V3, V4, V5) :- copy_term(GV+FC5, GV+C5), call(C5, V1, V2, V3, V4, V5).
108
+ +\(GV, FC6, V1, V2, V3, V4, V5, V6) :- copy_term(GV+FC6, GV+C6), call(C6, V1, V2, V3, V4, V5, V6).
109
+ +\(GV, FC7, V1, V2, V3, V4, V5, V6, V7) :- copy_term(GV+FC7, GV+C7), call(C7, V1, V2, V3, V4, V5, V6, V7).
110
+
111
+ lambda__no_hat_call(Goal) :-
112
+ nonvar(Goal),
113
+ Goal = (_^_),
114
+ !,
115
+ throw(error(existence_error(lambda_parameter, Goal), _)).
116
+ lambda__no_hat_call(Goal) :- call(Goal).
@@ -13,6 +13,7 @@ const moduleFiles = Object.freeze({
13
13
  comparison: 'comparison.pl',
14
14
  dates: 'dates.pl',
15
15
  iso_ext: 'iso_ext.pl',
16
+ lambda: 'lambda.pl',
16
17
  lists: 'lists.pl',
17
18
  primes: 'primes.pl',
18
19
  prologue: 'prologue.pl',
@@ -68,6 +69,9 @@ export const eyePrologPortableLibraryIndicators = Object.freeze([
68
69
  'length/2', 'sum_list/2', 'min_list/2', 'max_list/2', 'list_to_set/2',
69
70
  'succ/2', 'foldl/4', 'foldl/5', 'foldl/6',
70
71
  'forall/2', 'cfor/3', 'findall/4', 'variant/2', 'uuid/3',
72
+ '^/3', '^/4', '^/5', '^/6', '^/7', '^/8', '^/9', '^/10',
73
+ '\\/1', '\\/2', '\\/3', '\\/4', '\\/5', '\\/6', '\\/7', '\\/8',
74
+ '+\\/2', '+\\/3', '+\\/4', '+\\/5', '+\\/6', '+\\/7', '+\\/8', '+\\/9',
71
75
  ]);
72
76
  export const eyePrologLibraryIndicators = Object.freeze([
73
77
  ...eyePrologPortableLibraryIndicators,
@@ -127,7 +131,7 @@ export const eyePrologInteropLibraryIndicators = Object.freeze(
127
131
  // Libraries whose *name* is part of the current interop profile. A program
128
132
  // may freely use_module/1 with these common module names; predicates in those
129
133
  // modules outside eyePrologInteropLibraryIndicators are still diagnosed when used.
130
- export const eyePrologInteropLibraryModules = Object.freeze(['lists', 'iso_ext']);
134
+ export const eyePrologInteropLibraryModules = Object.freeze(['lists', 'iso_ext', 'lambda']);
131
135
 
132
136
  function* tabledNegationBuiltin({ solver, goal, env }) {
133
137
  yield* solver.solveTabledNegation(goal.args[0], env);
@@ -3307,6 +3307,68 @@ check(A, B, C, D, E, F) :-
3307
3307
  assertIncludes(result.stdout, 'check("ab", "a", "ab", [a - 1, b - 2], 6, "a").\n', 'stdout');
3308
3308
  },
3309
3309
  },
3310
+ {
3311
+ name: 'library(lambda) supports Scryer-style maplist lambdas',
3312
+ run: () => {
3313
+ const source = String.raw`:- use_module(library(lambda)).
3314
+ :- use_module(library(lists)).
3315
+ answer :- maplist(\X^(X>3), [4,5,9]).
3316
+ `;
3317
+ const result = run(source, { goal: 'answer' });
3318
+ assertEqual(result.stdout, 'answer.\n', 'stdout');
3319
+ },
3320
+ },
3321
+ {
3322
+ name: 'library(lambda) refreshes local variables on each invocation',
3323
+ run: () => {
3324
+ const source = String.raw`:- use_module(library(lambda)).
3325
+ :- use_module(library(lists)).
3326
+ answer :- maplist(\X^(Y=X), [a,b]).
3327
+ `;
3328
+ const result = run(source, { goal: 'answer' });
3329
+ assertEqual(result.stdout, 'answer.\n', 'fresh local variables');
3330
+ },
3331
+ },
3332
+ {
3333
+ name: 'library(lambda) preserves explicitly free variables with +\\',
3334
+ run: () => {
3335
+ const source = String.raw`:- use_module(library(lambda)).
3336
+ :- use_module(library(lists)).
3337
+ answer(Y) :- maplist(Y+\X^(Y=X), [a,a]).
3338
+ `;
3339
+ const program = Program.parse(source);
3340
+ const imported = [...program.operators.values()].find((operator) => operator.name === '+\\');
3341
+ assertEqual(`${imported?.priority}/${imported?.specifier}`, '201/xfx', '+\\ operator import');
3342
+ const result = run(program, { goal: 'answer(Y)' });
3343
+ assertEqual(result.stdout, 'answer(a).\n', 'free variable sharing');
3344
+ },
3345
+ },
3346
+ {
3347
+ name: 'library(lambda) supports continuations and seven call arguments',
3348
+ run: () => {
3349
+ const source = String.raw`:- use_module(library(lambda)).
3350
+ f(x,y).
3351
+ tuple(a,b,c,d,e,f,g).
3352
+ answer(A,B) :-
3353
+ call(\X^f(X), A, B),
3354
+ call(\X^Y^f(X,Y), A, B),
3355
+ call(\P^Q^R^S^T^U^V^tuple(P,Q,R,S,T,U,V), a,b,c,d,e,f,g).
3356
+ `;
3357
+ const result = run(source, { goal: 'answer(A,B)' });
3358
+ assertEqual(result.stdout, 'answer(x, y).\n', 'continuations');
3359
+ },
3360
+ },
3361
+ {
3362
+ name: 'library(lambda) diagnoses a missing lambda parameter',
3363
+ run: () => {
3364
+ const source = String.raw`:- use_module(library(lambda)).
3365
+ answer(ok) :-
3366
+ catch(call(\X^true), error(existence_error(lambda_parameter,_),_), true).
3367
+ `;
3368
+ const result = run(source, { goal: 'answer(X)' });
3369
+ assertEqual(result.stdout, 'answer(ok).\n', 'lambda parameter error');
3370
+ },
3371
+ },
3310
3372
  {
3311
3373
  name: 'autoload metadata records canonical interop imports',
3312
3374
  run: () => {
@@ -3733,16 +3795,16 @@ check(A, B, C, D, E, F) :-
3733
3795
  assertEqual(registry.get('tnot', 1), null, 'tnot/1 is absent from the ISO registry');
3734
3796
  assertEqual(Boolean(library.get('tnot', 1)), true, 'tnot/1 is an EyeProlog WFS extension');
3735
3797
  assertEqual(registeredNativeEyePrologLibraryNames().length, 40, 'public native EyeProlog builtin count');
3736
- assertEqual(eyePrologPortableLibraryIndicators.length, 62, 'portable Prolog library count');
3798
+ assertEqual(eyePrologPortableLibraryIndicators.length, 86, 'portable Prolog library count');
3737
3799
  assertEqual(eyePrologInteropLibraryIndicators.length, 27, 'cross-implementation interop profile count');
3738
- assertEqual(eyePrologInteropLibraryModules.join(','), 'lists,iso_ext', 'common explicit library module profile');
3800
+ assertEqual(eyePrologInteropLibraryModules.join(','), 'lists,iso_ext,lambda', 'common explicit library module profile');
3739
3801
  assertEqual(eyePrologInteropAutoload['member/2'], 'lists', 'member/2 canonical autoload');
3740
3802
  assertEqual(eyePrologInteropAutoload['between/3'], 'prologue', 'between/3 canonical internal autoload');
3741
3803
  assertEqual(eyePrologInteropAutoload['call_nth/2'], 'iso_ext', 'call_nth/2 canonical interop autoload');
3742
3804
  assertEqual(eyePrologInteropAutoload['set_nth0/4'] ?? null, null, 'EyeProlog-only set_nth0/4 is not autoloadable');
3743
3805
  assertEqual(eyePrologNativeLibraryIndicators.length, 40, 'native host library count');
3744
3806
  assertEqual(eyePrologNativeLibraryIndicators.slice(0, 2).join(','), 'call_nth/2,freeze/2', 'control predicates requiring host support');
3745
- assertEqual(eyePrologLibraryIndicators.length, 102, 'complete EyeProlog library surface');
3807
+ assertEqual(eyePrologLibraryIndicators.length, 126, 'complete EyeProlog library surface');
3746
3808
  assertEqual(registry.get('eyeprolog__call_nth', 2), null, 'private call_nth adapter is absent from ISO registry');
3747
3809
  assertEqual(Boolean(library.get('eyeprolog__call_nth', 2)), true, 'private call_nth adapter is registered for EyeProlog');
3748
3810
  assertEqual(library.get('eyeprolog__call_nth', 2)?.eyePrologLibrary, true, 'private adapter is marked as library support');
@@ -6039,19 +6039,19 @@ so side effects occur in Prolog execution order.
6039
6039
 
6040
6040
  ### The EyeProlog library
6041
6041
 
6042
- EyeProlog exposes **102 library predicate indicators** in addition to the 129
6043
- indicators in its isolated ISO profile. **63 are defined as ordinary Prolog
6042
+ EyeProlog exposes **126 library predicate indicators** in addition to the 129
6043
+ indicators in its isolated ISO profile. **87 are defined as ordinary Prolog
6044
6044
  clauses** in focused modules under `src/lib/`. The remaining 39
6045
6045
  are public wrappers around backtrackable host support: Prologue `call_nth/2` and
6046
6046
  `freeze/2`, plus the 37-predicate finite-domain `library(clpz)` kernel. The
6047
- resulting normal EyeProlog language surface is therefore **228 public predicate
6047
+ resulting normal EyeProlog language surface is therefore **255 public predicate
6048
6048
  indicators**. Internally, the runtime registry contains the 129 ISO definitions
6049
6049
  plus 23 private library adapters; public relations remain module source clauses.
6050
6050
 
6051
6051
  The sources are `src/lib/aggregate.pl`, `src/lib/clpz.pl`, `src/lib/comparison.pl`,
6052
- `src/lib/dates.pl`, `src/lib/iso_ext.pl`, `src/lib/lists.pl`,
6053
- `src/lib/primes.pl`, `src/lib/prologue.pl`, `src/lib/random.pl`,
6054
- `src/lib/strings.pl`, and `src/lib/uuid.pl`. Each declares a same-named module
6052
+ `src/lib/dates.pl`, `src/lib/iso_ext.pl`, `src/lib/lambda.pl`,
6053
+ `src/lib/lists.pl`, `src/lib/primes.pl`, `src/lib/prologue.pl`,
6054
+ `src/lib/random.pl`, `src/lib/strings.pl`, and `src/lib/uuid.pl`. Each declares a same-named module
6055
6055
  with `module/2`; there is no catch-all `library(eyeprolog)`. A program imports
6056
6056
  only the modules it needs, and
6057
6057
  `use_module/2` can select an even smaller indicator list. The Prologue
@@ -6083,6 +6083,7 @@ between solution branches.
6083
6083
  | `library(comparison)` | `lt/2`, `gt/2`, `le/2`, `ge/2` |
6084
6084
  | `library(dates)` | `difference/3` |
6085
6085
  | `library(iso_ext)` | `call_nth/2`, `countall/2`, `forall/2`, `succ/2`, `cfor/3`, `findall/4`, `variant/2` |
6086
+ | `library(lambda)` | `^/3`, `^/4`, `^/5`, `^/6`, `^/7`, `^/8`, `^/9`, `^/10`, `\/1`, `\/2`, `\/3`, `\/4`, `\/5`, `\/6`, `\/7`, `\/8`, `+\/2`, `+\/3`, `+\/4`, `+\/5`, `+\/6`, `+\/7`, `+\/8`, `+\/9` |
6086
6087
  | `library(lists)` | `member/2`, `memberchk/2`, `select/3`, `append/2`, `append/3`, `last/2`, `same_length/2`, `nth0/3`, `nth0/4`, `nth1/3`, `nth1/4`, `reverse/2`, `length/2`, `maplist/2`, `maplist/3`, `maplist/4`, `maplist/5`, `maplist/6`, `maplist/7`, `maplist/8`, `foldl/4`, `foldl/5`, `foldl/6`, `sum_list/2`, `min_list/2`, `max_list/2`, `list_to_set/2`, `set_nth0/4`, `take/3`, `drop/3`, `slice/4` |
6087
6088
  | `library(primes)` | `smallest_divisor_from/3` |
6088
6089
  | `library(prologue)` | `member/2`, `append/3`, `length/2`, `between/3`, `select/3`, `succ/2`, `maplist/2`, `maplist/3`, `maplist/4`, `maplist/5`, `maplist/6`, `maplist/7`, `maplist/8`, `nth0/3`, `nth0/4`, `nth1/3`, `nth1/4`, `call_nth/2`, `freeze/2`, `foldl/4`, `foldl/5`, `foldl/6`, `countall/2` |
@@ -6118,6 +6119,39 @@ so a source file may import both without an accidental predicate collision.
6118
6119
  overlap these modules; use selective imports when legacy code combines it with
6119
6120
  the aligned libraries.
6120
6121
 
6122
+ `library(lambda)` is an explicitly imported Scryer-aligned module for
6123
+ higher-order programming. Its implementation is adapted from Ulrich Neumerkel's
6124
+ `library(lambda)` as distributed by Scryer Prolog, retaining the upstream
6125
+ copyright and redistribution notice. The public syntax is:
6126
+
6127
+ ```text
6128
+ \X1^X2^...^XN^Goal
6129
+ Free+\X1^X2^...^XN^Goal
6130
+ ```
6131
+
6132
+ The first form has no explicitly shared free variables. Before each invocation
6133
+ EyeProlog copies the closure term, so local variables are fresh on successive
6134
+ `maplist/2-8`, `foldl/4-6`, or direct `call/N` uses. In the second form, the
6135
+ variables contained in `Free` remain shared with the surrounding goal. Importing
6136
+ the library installs `+\` as a priority-201 `xfx` operator; `\` and `^` use
6137
+ their existing ISO operator definitions. Parenthesize lower-priority goal
6138
+ operators after `^`, for example `\X^(X > 3)`.
6139
+
6140
+ A continuation lambda may leave arguments for a later call:
6141
+
6142
+ ```text
6143
+ f(x, y).
6144
+
6145
+ answer(A, B) :- call(\X^f(X), A, B).
6146
+ ```
6147
+
6148
+ This is equivalent to supplying both arguments directly. A lambda that is
6149
+ called with too few parameters raises `existence_error(lambda_parameter, ...)`,
6150
+ matching the diagnostic intent of the Scryer library. EyeProlog uses its ISO
6151
+ `copy_term/2` implementation for the fresh-copy step; in EyeProlog this gives
6152
+ the natural-copy behavior needed by the library without requiring a separate
6153
+ `copy_term_nat/2` predicate.
6154
+
6121
6155
  Normal EyeProlog execution can autoload an otherwise undefined unqualified call
6122
6156
  only when the interop table assigns it one canonical provider. Thus `member/2`
6123
6157
  autoloads from `library(lists)`, `call_nth/2` from `library(iso_ext)`, and