Lets make an example what is meant by lexically assigned
module context. Its the same idea like Scheme lexical scoping.
It is defined as follows:
3.4.4 Lexical Scope
The rules that we have just been describing are the details of how
Scheme implements “lexical scoping”. This subsection takes a brief diversion to explain what lexical scope means in general and to
present an example of non-lexical scoping.
“Lexical scope” in general is the idea that
- an identifier at a particular place in a program always refers to
the same variable location — where “always” means “every time
that the containing expression is executed”, and that
- the variable location to which it refers can be determined by
static examination of the source code context in which that
identifier appears, without having to consider the flow of
execution through the program as a whole.
https://www.gnu.org/software/guile/manual/html_node/Lexical-Scope.html
Concerning Lexical Scoping and Module System:
- SWI-Prolog doesn't implement lexical scoping by default.
- Jekejeke Prolog implements lexical scoping by default.
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 22:53:13 UTC+2:
I am in the preparation phase of a module system for
the Dogelog Runtime. It will implement some ideas of
LeanTalk. Some of these ideas are already realized in
Jekejeke Prolog. But Jekejeke Prolog suffers from
the use of (:)/2 and (::)/2. The operator (:)/2 is in collision
with the Prolog dicts. So the module system should
not make use of the operator (:)/2. We need to find
a new operator. Suggestion is to use the operator (.)/2
and a preliminarly named operator '$MOD'/2.
'$MOD'/2, which might be renamed later, is only for
input/output. It should show the module context that
is lexically assigned to the atoms during reading of
atoms. Jekejeke Prolog cannot yet input/output '$MOD'/2,
there is only a read/write option source. Dogelog Runtime
will have the same read/write option source, but additionally
support '$MOD'/2.
I am in the preparation phase of a module system for
the Dogelog Runtime. It will implement some ideas of
LeanTalk. Some of these ideas are already realized in
Jekejeke Prolog. But Jekejeke Prolog suffers from
the use of (:)/2 and (::)/2. The operator (:)/2 is in collision
with the Prolog dicts. So the module system should
not make use of the operator (:)/2. We need to find
a new operator. Suggestion is to use the operator (.)/2
and a preliminarly named operator '$MOD'/2.
'$MOD'/2, which might be renamed later, is only for
input/output. It should show the module context that
is lexically assigned to the atoms during reading of
atoms. Jekejeke Prolog cannot yet input/output '$MOD'/2,
there is only a read/write option source. Dogelog Runtime
will have the same read/write option source, but additionally
support '$MOD'/2.
Here is a test case that shows that SWI-Prolog doesn't know
lexical scoping, whereas Jekejeke Prolog implements lexical
scoping. The test case executed in SWI-Prolog and Jekejeke Prolog:
SWI-Prolog No Lexical Scoping:
?- module(foo).
foo: ?- [user].
test(X) :- X =.. [test2].
test2 :- write('Hello World!'), nl.
^D
foo: ?- test(X), X.
Hello World!
foo: ?- module(user).
?- foo:test(X), X.
ERROR: Unknown procedure: test2/0
Jekejeke Prolog Lexical Scoping:
?- begin_module(foo).
(foo) ?- [user].
test(X) :- X =.. [test2].
test2 :- write('Hello World!'), nl.
^D
(foo) ?- test(X), X.
Hello World!
(foo) ?- end_module.
?- foo:test(X), X.
Hello World!
See the difference?
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 22:56:37 UTC+2:
Lets make an example what is meant by lexically assigned
module context. Its the same idea like Scheme lexical scoping.
It is defined as follows:
3.4.4 Lexical Scope
The rules that we have just been describing are the details of how
Scheme implements “lexical scoping”. This subsection takes a brief diversion to explain what lexical scope means in general and to
present an example of non-lexical scoping.
“Lexical scope” in general is the idea that
- an identifier at a particular place in a program always refers to
the same variable location — where “always” means “every time
that the containing expression is executed”, and that
- the variable location to which it refers can be determined by
static examination of the source code context in which that
identifier appears, without having to consider the flow of
execution through the program as a whole.
https://www.gnu.org/software/guile/manual/html_node/Lexical-Scope.html
Concerning Lexical Scoping and Module System:
- SWI-Prolog doesn't implement lexical scoping by default.
- Jekejeke Prolog implements lexical scoping by default.
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 22:53:13 UTC+2:
I am in the preparation phase of a module system for
the Dogelog Runtime. It will implement some ideas of
LeanTalk. Some of these ideas are already realized in
Jekejeke Prolog. But Jekejeke Prolog suffers from
the use of (:)/2 and (::)/2. The operator (:)/2 is in collision
with the Prolog dicts. So the module system should
not make use of the operator (:)/2. We need to find
a new operator. Suggestion is to use the operator (.)/2
and a preliminarly named operator '$MOD'/2.
'$MOD'/2, which might be renamed later, is only for
input/output. It should show the module context that
is lexically assigned to the atoms during reading of
atoms. Jekejeke Prolog cannot yet input/output '$MOD'/2,
there is only a read/write option source. Dogelog Runtime
will have the same read/write option source, but additionally
support '$MOD'/2.
So what will be different in Dogelog Runtime? After Jekejeke
Prolog has already lexical scoping, how will the Dogelog Runtime
differ? One change is to use the operator '.'/2 in place of (:)/2
and introduce the operator '$MOD'/2. Lets look at the last
query in Jekejeke Prolog, and project into the future how this
last query should work out in the Dogelog Runtime.
Currently in Jekejeke Prolog:
?- foo:test(X), X. %%% the operator (:)/2 is used, conflict with Dicts
Hello World!
X = test2 %%% no indication of lexical scope
Projected for Dogelog Runtime:
?- foo.test(X), X. %%% the operator ('.')/2 should be used
Hello World!
X = '$MOD'(foo,test2) %%% indicates the lexical scope of test2
We would like to use the shorter (:)/2 for '$MOD'/2, but if
we ban (:)/2 because of conflict with Dicts, we can
also not use it for what '$MOD'/2 will do.
'$MOD'/2 is only present in input/output. But internally
it disappears. Unlike ('.')/2 it cannot be used to change
the lexical scope. The lexical scope is attached to
the atoms, and '$MOD'/2 can show the first atom that
changes the lexical scope. A written term might have
multiple '$MOD'/2 for every lexical scope change.
More readable would be some infix operator, but so many
operators have meaning in other Prolog systems, so
we will first work with '$MOD'/2 and maybe find a short
operator and replace it later.
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 23:00:47 UTC+2:
Here is a test case that shows that SWI-Prolog doesn't know
lexical scoping, whereas Jekejeke Prolog implements lexical
scoping. The test case executed in SWI-Prolog and Jekejeke Prolog:
SWI-Prolog No Lexical Scoping:
?- module(foo).
foo: ?- [user].
test(X) :- X =.. [test2].
test2 :- write('Hello World!'), nl.
^D
foo: ?- test(X), X.
Hello World!
foo: ?- module(user).
?- foo:test(X), X.
ERROR: Unknown procedure: test2/0
Jekejeke Prolog Lexical Scoping:
?- begin_module(foo).
(foo) ?- [user].
test(X) :- X =.. [test2].
test2 :- write('Hello World!'), nl.
^D
(foo) ?- test(X), X.
Hello World!
(foo) ?- end_module.
?- foo:test(X), X.
Hello World!
See the difference?
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 22:56:37 UTC+2:
Lets make an example what is meant by lexically assigned
module context. Its the same idea like Scheme lexical scoping.
It is defined as follows:
3.4.4 Lexical Scope
The rules that we have just been describing are the details of how Scheme implements “lexical scoping”. This subsection takes a brief diversion to explain what lexical scope means in general and to
present an example of non-lexical scoping.
“Lexical scope” in general is the idea that
- an identifier at a particular place in a program always refers to
the same variable location — where “always” means “every time that the containing expression is executed”, and that
- the variable location to which it refers can be determined by
static examination of the source code context in which that
identifier appears, without having to consider the flow of
execution through the program as a whole.
https://www.gnu.org/software/guile/manual/html_node/Lexical-Scope.html
Concerning Lexical Scoping and Module System:
- SWI-Prolog doesn't implement lexical scoping by default.
- Jekejeke Prolog implements lexical scoping by default.
Mostowski Collapse schrieb am Dienstag, 14. September 2021 um 22:53:13 UTC+2:
I am in the preparation phase of a module system for
the Dogelog Runtime. It will implement some ideas of
LeanTalk. Some of these ideas are already realized in
Jekejeke Prolog. But Jekejeke Prolog suffers from
the use of (:)/2 and (::)/2. The operator (:)/2 is in collision
with the Prolog dicts. So the module system should
not make use of the operator (:)/2. We need to find
a new operator. Suggestion is to use the operator (.)/2
and a preliminarly named operator '$MOD'/2.
'$MOD'/2, which might be renamed later, is only for
input/output. It should show the module context that
is lexically assigned to the atoms during reading of
atoms. Jekejeke Prolog cannot yet input/output '$MOD'/2,
there is only a read/write option source. Dogelog Runtime
will have the same read/write option source, but additionally
support '$MOD'/2.
More stuff that Logtalk can only dream of. In Dogelog Runtime we
recently introduced a new type tester called symbol/1. One can
imagine that it is bootstrapped from blob/2 as follows:
symbol(X) :- blob(X, _).
Dogelog Runtime does also accept symbols as functors, similar
like SWI-Prolog. This is used to inline disjunction and if-then-else,
and could have further optimization use cases. Functors are not
only restricted to atoms, they can be atoms or references:
/* Dogelog Runtime, 0.9.6 */
?- current_input(X), atom(X).
fail.
?- current_input(X), Y =.. [X, bar].
X = [object Object], Y = [object Object](bar).
See also:
Is there a Prolog name for atom/1 or stream/1 etc (SWI-Prolog) https://stackoverflow.com/q/69137776/502187
The symbol/1 question also marks my return to stackoverflow,
for SWI-Prolog related questions. SWI-Prolog discourse has
become totally unusable due to its censoring.
If they cannot attack you directly. They start censoring other
peoples threads where you participate. And disown thread
owners (sic!). They did censor based on frequency of posts,
you hear arguments like "leave room for other people". They
did the same when Paulo Moura was in the SWI-Prolog group,
and I had the suspicion that most of the negative censoring
came from Paulo Moura. But since Paulo Moura has left the
SWI-Prolog group it is clear where the negative censoring
comes from. Most likely Paulo Moura is half as evil as I
thought, and the negative censoring is home made.
But I am currently thinking about extending (=..)/2 even more.
Namely to allow a compound as functor. What should a
compound as functor do? Very simple:
/* Expected Result */
?- X =.. [foo(bar), baz].
X = foo(bar, baz)
So (=..)/2 would add the arguments to the given compound. This
further extension of (=..)/2 doesn't need a new data type in the
compound functor, but rather changes its behaviour.
It would have a couple of use cases:
-Old Higher Order:
Bootstrapping apply/2 would be as easy as:
apply(X,L) :- G =.. [X|L], G.
- New Higher Order:
Bottstrapping call/n would be as easy as:
call(X,Y) :- G =.. [X,Y], G.
call(X,Y,Z) :- G =.. [X,Y,Z], G.
call(X,Y,Z,T) :- G =.. [X,Y,Z,T], G.
Etc..
-DCG Expansion:
Expanding a non-terminal by an input and output list
would be only a matter of calling (=..)/2. Here is an example:
?- G =.. [np(X),I,O].
G = np(X,I,O).
Mostowski Collapse schrieb am Freitag, 17. September 2021 um 14:07:57 UTC+2:
More stuff that Logtalk can only dream of. In Dogelog Runtime we
recently introduced a new type tester called symbol/1. One can
imagine that it is bootstrapped from blob/2 as follows:
symbol(X) :- blob(X, _).
Dogelog Runtime does also accept symbols as functors, similar
like SWI-Prolog. This is used to inline disjunction and if-then-else,
and could have further optimization use cases. Functors are not
only restricted to atoms, they can be atoms or references:
/* Dogelog Runtime, 0.9.6 */
?- current_input(X), atom(X).
fail.
?- current_input(X), Y =.. [X, bar].
X = [object Object], Y = [object Object](bar).
See also:
Is there a Prolog name for atom/1 or stream/1 etc (SWI-Prolog) https://stackoverflow.com/q/69137776/502187
A few weeks ago I would have posted the same idea on
SWI-Prolog discourse. But since I got massively censored
I will not anymore post anything on SWI-Prolog discourse.
On the otherhand I feel quite unrestricted on the Python
usenet list. The people there seem to be much less
envious than on SWI-Prolog discourse. Just imagine,
I went to the Python list, and told them 10x times that
Python, especially the Python version of Dogelog Runtime,
was extremly slow. There wasn't really a uproar or shit storm.
SWI-Prolog would already have lost it in the first second,
and censored every bit of what I was asking or reporting.
Python usenet group showed some professionality.
LoL
Mostowski Collapse schrieb am Freitag, 17. September 2021 um 14:11:37 UTC+2:
But I am currently thinking about extending (=..)/2 even more.
Namely to allow a compound as functor. What should a
compound as functor do? Very simple:
/* Expected Result */
?- X =.. [foo(bar), baz].
X = foo(bar, baz)
So (=..)/2 would add the arguments to the given compound. This
further extension of (=..)/2 doesn't need a new data type in the
compound functor, but rather changes its behaviour.
It would have a couple of use cases:
-Old Higher Order:
Bootstrapping apply/2 would be as easy as:
apply(X,L) :- G =.. [X|L], G.
- New Higher Order:
Bottstrapping call/n would be as easy as:
call(X,Y) :- G =.. [X,Y], G.
call(X,Y,Z) :- G =.. [X,Y,Z], G.
call(X,Y,Z,T) :- G =.. [X,Y,Z,T], G.
Etc..
-DCG Expansion:
Expanding a non-terminal by an input and output list
would be only a matter of calling (=..)/2. Here is an example:
?- G =.. [np(X),I,O].
G = np(X,I,O).
Mostowski Collapse schrieb am Freitag, 17. September 2021 um 14:07:57 UTC+2:
More stuff that Logtalk can only dream of. In Dogelog Runtime we
recently introduced a new type tester called symbol/1. One can
imagine that it is bootstrapped from blob/2 as follows:
symbol(X) :- blob(X, _).
Dogelog Runtime does also accept symbols as functors, similar
like SWI-Prolog. This is used to inline disjunction and if-then-else,
and could have further optimization use cases. Functors are not
only restricted to atoms, they can be atoms or references:
/* Dogelog Runtime, 0.9.6 */
?- current_input(X), atom(X).
fail.
?- current_input(X), Y =.. [X, bar].
X = [object Object], Y = [object Object](bar).
See also:
Is there a Prolog name for atom/1 or stream/1 etc (SWI-Prolog) https://stackoverflow.com/q/69137776/502187
Do you say Python should not be used to implement
such things? In my opinion, Python has a high potential
to implement Prolog, because it has also ast.parse()
and compile(). But I do not yet have a showcase that uses
these features of Python to compile Prolog. I dont work 24/7
and I cannot clone myself. Currently the Prolog code is interpreted.
I have a prototype where Prolog code is compiled into JavaScript,
but I did not yet try this approach with Python. Here you see how
JavaScript closures are generated, a first prototype:
const alt4 = make_defined([new Clause(1, [0, 0], function(
display, actual, cont) {return(new Compound(".", [new Compound(
"==", [deref(actual.args[0]), "end_of_file"]), new Compound(
".", [new Compound("$CUT", [deref(display[0])]), cont
])]))}, 0, undefined), new Clause(1, [0, 0], function(
display, actual, cont) {return(new Compound(".", [new Compound( "expand_include", [deref(actual.args[0]), deref(actual.args[1]
), display[0] = new Variable()]), new Compound(".",
[new Compound("handle_term", [deref(display[0])]), new Compound(
".", ["fail", cont])])]))}, -1, undefined)]);
add("next_term", 1, new Clause(2, [0], function(display, actual,
cont) {return(new Compound(".", [new Compound("read_term", [deref(actual.args[0]), display[0] = new Variable(),
new Compound(".", [new Compound("variable_names", [
display[1] = new Variable()]), "[]"])]), new Compound(
".", [new Compound(alt4, [deref(display[0]), deref(
display[1])]), cont])]))}, -1, undefined));
https://github.com/jburse/dogelog-moon/issues/184
Will do the same for Python in the next weeks. Then later this approach
will be combined with a few planned optimizations. So far got a 25%
speed increase for JavaScript with this new compilation scheme, but
there is no official release out yet, that features this approach. And
there should be much more in it, also for Python.
Please be patient. A big problem with development can be
burnout. So I am trying to slow down things at the moment.
The ideas are easy to sketch, but implementation can take
weeks. Here is the idea again in a nutshell: use ast.parse()
and compile(). Or build directly an AST, not using the string
detour as in ast.parse(). How long will it take to have a
working solution? 11 years ago there was:
Pyrolog: Prolog written in Python using PyPy's RPython tool chain https://www.reddit.com/r/prolog/comments/fbuz1/pyrolog_prolog_written_in_python_using_pypys/
RPython is a framework for implementing interpreters and virtual
machines for programming languages, especially dynamic languages. https://rpython.readthedocs.io/en/latest/faq.html
Currently I am not planning to use RPython, want to to use
standard Python AST and compile(). Might have a look at
RPython or similar stuff later.
Mostowski Collapse schrieb am Sonntag, 19. September 2021 um 22:25:46 UTC+2:
Do you say Python should not be used to implement
such things? In my opinion, Python has a high potential
to implement Prolog, because it has also ast.parse()
and compile(). But I do not yet have a showcase that uses
these features of Python to compile Prolog. I dont work 24/7
and I cannot clone myself. Currently the Prolog code is interpreted.
I have a prototype where Prolog code is compiled into JavaScript,
but I did not yet try this approach with Python. Here you see how JavaScript closures are generated, a first prototype:
const alt4 = make_defined([new Clause(1, [0, 0], function(
display, actual, cont) {return(new Compound(".", [new Compound(
"==", [deref(actual.args[0]), "end_of_file"]), new Compound(
".", [new Compound("$CUT", [deref(display[0])]), cont
])]))}, 0, undefined), new Clause(1, [0, 0], function(
display, actual, cont) {return(new Compound(".", [new Compound( "expand_include", [deref(actual.args[0]), deref(actual.args[1]
), display[0] = new Variable()]), new Compound(".",
[new Compound("handle_term", [deref(display[0])]), new Compound(
".", ["fail", cont])])]))}, -1, undefined)]);
add("next_term", 1, new Clause(2, [0], function(display, actual,
cont) {return(new Compound(".", [new Compound("read_term", [deref(actual.args[0]), display[0] = new Variable(),
new Compound(".", [new Compound("variable_names", [
display[1] = new Variable()]), "[]"])]), new Compound(
".", [new Compound(alt4, [deref(display[0]), deref(
display[1])]), cont])]))}, -1, undefined));
https://github.com/jburse/dogelog-moon/issues/184
Will do the same for Python in the next weeks. Then later this approach will be combined with a few planned optimizations. So far got a 25%
speed increase for JavaScript with this new compilation scheme, but
there is no official release out yet, that features this approach. And there should be much more in it, also for Python.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 292 |
Nodes: | 16 (2 / 14) |
Uptime: | 203:37:06 |
Calls: | 6,617 |
Calls today: | 1 |
Files: | 12,168 |
Messages: | 5,316,470 |