• How working with GitHub feels (Was: 50 Years of Prolog Nonsense)

    From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Wed Mar 13 14:45:59 2024
    From Newsgroup: comp.lang.prolog

    Yeah today I created a ticket in GitHub issues.
    Now I need to take a SPA nap:

    Cute Kitten Really Enjoys SPA
    https://www.youtube.com/watch?v=L7lVrWY9zQE

    P.S.: No wonder Scryer Prolog has 242 tickets: https://github.com/mthom/scryer-prolog/issues

    Mostowski Collapse schrieb:
    Rounding still not fixed in Scryer Prolog. Look
    what a nice test case I am using:

    ?- atom_integer(X, 2, 166153499473114502559719956244594689).
    X = '1000000000000000000000000000000000000000 000000000000010000000000000000000000000000000 000000000000000000000000000000001'.

    And whats the result:

    $ target/release/scryer-prolog -v
    "v0.9.1-151-g17450520"
    $ target/release/scryer-prolog
    ?- X is float(166153499473114502559719956244594689).
    X = 1.661534994731145e35.
    ?- Y = 1.6615349947311452e+35.
    Y = 1.6615349947311452e35.
    ?- X is float(166153499473114502559719956244594689)-1.6615349947311452e+35.
    X = -3.6893488147419103e19.
    ?-

    Its not correctly rounded!


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Wed Mar 13 15:05:34 2024
    From Newsgroup: comp.lang.prolog


    Or maybe its a seasonal effect related to Springtime lethargy. https://en.wikipedia.org/wiki/Springtime_lethargy.

    Mild Shock schrieb:
    Yeah today I created a ticket in GitHub issues.
    Now I need to take a SPA nap:

    Cute Kitten Really Enjoys SPA
    https://www.youtube.com/watch?v=L7lVrWY9zQE

    P.S.: No wonder Scryer Prolog has 242 tickets: https://github.com/mthom/scryer-prolog/issues

    Mostowski Collapse schrieb:
    Rounding still not fixed in Scryer Prolog. Look
    what a nice test case I am using:

    ?- atom_integer(X, 2, 166153499473114502559719956244594689).
    X = '1000000000000000000000000000000000000000
    000000000000010000000000000000000000000000000
    000000000000000000000000000000001'.

    And whats the result:

    $ target/release/scryer-prolog -v
    "v0.9.1-151-g17450520"
    $ target/release/scryer-prolog
    ?- X is float(166153499473114502559719956244594689).
        X = 1.661534994731145e35.
    ?- Y = 1.6615349947311452e+35.
        Y = 1.6615349947311452e35.
    ?- X is
    float(166153499473114502559719956244594689)-1.6615349947311452e+35.
        X = -3.6893488147419103e19.
    ?-

    Its not correctly rounded!



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sun Sep 29 17:22:45 2024
    From Newsgroup: comp.lang.prolog

    Hi,

    How did the basilisk lived so long at the chamber of
    secrets? I always just figured they were excellent at
    hibernating and only awoke once called for.

    How it started:

    We hope that a collection of PIPs will
    increase the visibility of Prolog and its growth. https://prolog-lang.pages.software.imdea.org/implementors-forum/FAQ.html

    How its going:

    11:00-11:15 Proposal: Binary prefix operators. Presenter: François Fages 11:15-11:30 Proposal: CSV interface. Presenter: Daniel Jurjo https://prolog-lang.org/ImplementersForum/PIPWorkshop2024.html

    These talks will possibly be published in some
    Spinger Journal behind a paywall right?

    Nobody has seen these PIPs elsewhere so far.

    Bye
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Fri Nov 8 15:07:23 2024
    From Newsgroup: comp.lang.prolog

    Hi,

    Interestingly in the old times, Prolog dicts that
    are functional datastructures were called
    multiple version hash tables (MVIIT):

    Hash Tables in Logic Programming
    The paper gives informal semantics for hash tables
    as partial functions on logical terms for Prolog's
    Horn clause language, and the implementation has been
    used in Tricia, an implementation of Prolog
    developed at Uppsala University.
    Jonas Barklund and Hakan Millroth,
    International Conference on Logic Programming 1987, https://www2.it.uu.se/research/csd/reports/0040.pdf

    Oki Doki

    Bye

    Mild Shock schrieb:
    Hi,

    How did the basilisk lived so long at the chamber of
    secrets? I always just figured they were excellent at
    hibernating and only awoke once called for.

    How it started:

    We hope that a collection of PIPs will
    increase the visibility of Prolog and its growth. https://prolog-lang.pages.software.imdea.org/implementors-forum/FAQ.html

    How its going:

    11:00-11:15 Proposal: Binary prefix operators. Presenter: François Fages 11:15-11:30 Proposal: CSV interface. Presenter: Daniel Jurjo https://prolog-lang.org/ImplementersForum/PIPWorkshop2024.html

    These talks will possibly be published in some
    Spinger Journal behind a paywall right?

    Nobody has seen these PIPs elsewhere so far.

    Bye

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Fri Nov 8 15:29:17 2024
    From Newsgroup: comp.lang.prolog

    Hi,

    Okay, there is another one. Now we are getting
    closer to change_arg/3, the physical representation
    of what was omitted in the previous paper

    now becomes a face. But its not really change_arg/3.
    What they try here is still multi versioned,
    so its more a change_arg/4. Maybe SWI-Prolog has

    something like this somewhere? I had setarg/4
    in formerly Jekejeke Prolog:

    Integrating Complex Data Structures in Prolog
    A number of data structures, primitive operations on
    them (which could not have been efficiently coded in
    Prolog) and various ways of integrating them in
    Edinburgh Prolog without destroying its
    uniformity are proposed.
    Jonas Barklund and Hakan Millroth - 1987
    International Conference on Spoken Language Processing}, https://www2.it.uu.se/research/csd/reports/0042.pdf

    Bye

    Mild Shock schrieb:
    Hi,

    Interestingly in the old times, Prolog dicts that
    are functional datastructures were called
    multiple version hash tables (MVIIT):

    Hash Tables in Logic Programming
    The paper gives informal semantics for hash tables
    as partial functions on logical terms for Prolog's
    Horn clause language, and the implementation has been
    used in Tricia, an implementation of Prolog
    developed at Uppsala University.
    Jonas Barklund and Hakan Millroth,
    International Conference on Logic Programming 1987, https://www2.it.uu.se/research/csd/reports/0040.pdf

    Oki Doki

    Bye

    Mild Shock schrieb:
    Hi,

    How did the basilisk lived so long at the chamber of
    secrets? I always just figured they were excellent at
    hibernating and only awoke once called for.

    How it started:

    We hope that a collection of PIPs will
    increase the visibility of Prolog and its growth.
    https://prolog-lang.pages.software.imdea.org/implementors-forum/FAQ.html

    How its going:

    11:00-11:15 Proposal: Binary prefix operators. Presenter: François Fages
    11:15-11:30 Proposal: CSV interface. Presenter: Daniel Jurjo
    https://prolog-lang.org/ImplementersForum/PIPWorkshop2024.html

    These talks will possibly be published in some
    Spinger Journal behind a paywall right?

    Nobody has seen these PIPs elsewhere so far.

    Bye


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Fri Nov 8 18:37:54 2024
    From Newsgroup: comp.lang.prolog

    I came up with a findall/3 for SWI-Prolog that
    doesn’t use call_cleanup/2. The findall2/3 realization
    uses nb_linkarg/3 and duplicate_term/2.

    findall2(Template, Goal, List) :-
    sys_find2_init(State),
    (Goal, sys_find2_next(Template, State), fail; true),
    sys_find2_fini(State, List).

    sys_find2_init(X) :-
    X = v(_,_),
    C = [-|_],
    nb_linkarg(1, X, C),
    nb_linkarg(2, X, C).

    sys_find2_next(T, X) :-
    C = [_|_],
    duplicate_term(T, H),
    nb_linkarg(1, C, H),
    arg(1, X, J), %%% known end cell
    nb_linkarg(2, J, C),
    nb_linkarg(1, X, C).

    sys_find2_fini(v(C,D), L) :-
    nb_linkarg(2, C, []),
    arg(2, D, L).

    Its not as fast as the bundled findall/3.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Fri Nov 8 18:39:26 2024
    From Newsgroup: comp.lang.prolog

    Interestingly the findall2/3 is not
    impressed by calling garbage_collect/0
    or trim_stacks/0:

    /* SWI-Prolog 9.3.14 */
    ?- findall2(Y-X-Y, (between(1,10,X);garbage_collect,
    trim_stacks, between(11,20,X)), L), write(L). [_212-1-_212,_230-2-_230,_248-3-_248,_266-4-_266, _284-5-_284,_302-6-_302,_320-7-_320,_338-8-_338, _356-9-_356,_374-10-_374,_396-11-_396,_418-12-_418, _440-13-_440,_462-14-_462,_484-15-_484,_506-16-_506, _528-17-_528,_550-18-_550,_572-19-_572,_594-20-_594]

    Memory consumption is also the same:

    ?- between(4,8,K), N is 10^K, space(findall(X,
    between(1,N,X),_)), fail; true.
    % Memory 0.229 mB
    % Memory 4.162 mB
    % Memory 33.522 mB
    % Memory 268.403 mB
    ERROR: Stack limit (1.0Gb) exceeded

    ?- between(4,8,K), N is 10^K, space(findall2(X,
    between(1,N,X),_)), fail; true.
    % Memory 0.393 mB
    % Memory 4.063 mB
    % Memory 33.423 mB
    % Memory 268.304 mB
    ERROR: Stack limit (1.0Gb) exceeded

    But I still do not 100% believe that
    it works...

    Mild Shock schrieb:
    I came up with a findall/3 for SWI-Prolog that
    doesn’t use call_cleanup/2. The findall2/3 realization
    uses nb_linkarg/3 and duplicate_term/2.

    findall2(Template, Goal, List) :-
       sys_find2_init(State),
       (Goal, sys_find2_next(Template, State), fail; true),
       sys_find2_fini(State, List).

    sys_find2_init(X) :-
       X = v(_,_),
       C = [-|_],
       nb_linkarg(1, X, C),
       nb_linkarg(2, X, C).

    sys_find2_next(T, X) :-
       C = [_|_],
       duplicate_term(T, H),
       nb_linkarg(1, C, H),
       arg(1, X, J),              %%% known end cell
       nb_linkarg(2, J, C),
       nb_linkarg(1, X, C).

    sys_find2_fini(v(C,D), L) :-
       nb_linkarg(2, C, []),
       arg(2, D, L).

    Its not as fast as the bundled findall/3.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Nov 9 15:47:59 2024
    From Newsgroup: comp.lang.prolog

    I can speed it up, if I use nb_setarg/3 instead
    of the explicit duplicate_term/2 and nb_linkarg/3 combo.
    The change is as follows:

    /* Before */
    sys_find2_next(T, X) :-
    C = [_|_],
    duplicate_term(T, H),
    nb_linkarg(1, C, H),
    arg(1, X, J),
    nb_linkarg(2, J, C),
    nb_linkarg(1, X, C)

    /* After */
    sys_find2_next(T, X) :-
    C = [_|_],
    nb_setarg(1, C, T),
    arg(1, X, J),
    nb_linkarg(2, J, C),
    nb_linkarg(1, X, C).

    Now the timings are better:

    /* Before */
    ?- time(test2).
    % 6,007,999 inferences, 0.422 CPU in 0.427
    seconds (99% CPU, 14241183 Lips)
    true.

    /* After */
    ?- time(test2).
    % 5,007,999 inferences, 0.297 CPU in 0.298
    seconds (100% CPU, 16869049 Lips)
    true.

    A wooping more than 100 milliseconds are gone!
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Nov 9 15:48:54 2024
    From Newsgroup: comp.lang.prolog

    With this little change it already beats all
    the call_cleanup/2 based findall/3 implementations
    around from some novell Prolog systems:

    /* Trealla Prolog 2.59.15 */
    ?- time(test).
    % Time elapsed 0.356s, 3004004 Inferences, 8.436 MLips
    true.

    /* Scryer Prolog 0.9.4-201 */
    ?- time(test).
    % CPU time: 0.464s, 5_062_044 inferences
    true.

    Mild Shock schrieb:
    I can speed it up, if I use nb_setarg/3 instead
    of the explicit duplicate_term/2 and nb_linkarg/3 combo.
    The change is as follows:

    /* Before */
    sys_find2_next(T, X) :-
       C = [_|_],
       duplicate_term(T, H),
       nb_linkarg(1, C, H),
       arg(1, X, J),
       nb_linkarg(2, J, C),
       nb_linkarg(1, X, C)

    /* After */
    sys_find2_next(T, X) :-
       C = [_|_],
       nb_setarg(1, C, T),
       arg(1, X, J),
       nb_linkarg(2, J, C),
       nb_linkarg(1, X, C).

    Now the timings are better:

    /* Before */
    ?- time(test2).
    % 6,007,999 inferences, 0.422 CPU in 0.427
    seconds (99% CPU, 14241183 Lips)
    true.

    /* After */
    ?- time(test2).
    % 5,007,999 inferences, 0.297 CPU in 0.298
    seconds (100% CPU, 16869049 Lips)
    true.

    A wooping more than 100 milliseconds are gone!

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sun Nov 10 12:37:14 2024
    From Newsgroup: comp.lang.prolog

    It all began with the bagof/3 choker:

    test :-
    bagof(X, N^(between(1,300,X), between(1,300,N),
    length(_,N)), _), fail; true.

    Which makes Prolog system tumble:

    /* SWI-Prolog 9.3.14 */
    ?- time(test).
    Action (h for help) ? abort
    % 468,739 inferences, 52.016 CPU in 53.069 seconds (98% CPU, 9012 Lips) Execution Aborted

    /* Scryer Prolog 0.9.4-201 */
    ?- time(test).
    ^C % CPU time: 110.153s, 145_508_466 inferences
    error('$interrupt_thrown',repl/0).

    Its mostlikely the same old problem that was
    observed years ago, in that the canonicalization
    of variables before the keysort/2 creates long

    instantiation chains. It can be solved by adjusting
    the unification order. Here is a take in Dogelog Player:

    /* Dogelog Player 1.2.5 */
    ?- time(test).
    % Zeit 7405 ms, GC 21 ms, Lips 3962971, Uhr 10.11.2024 00:57
    true.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sun Nov 10 12:40:24 2024
    From Newsgroup: comp.lang.prolog

    But we can also do without term_variables/3 or
    term_variable/2. don’ have tries in my system.
    But I recently introduced Okasaki tree, but it

    turned out that they are totally useless. What
    works better in my case was hash+keysort, as
    strange as it may sound.

    I believe it depends on the grouping factor.
    If there is a high grouping factor there is
    higher precentage of read from the grouping

    datastructure and than write into the
    grouping datastructure. So if read is only O(1)
    as in hash, you have better preformance than if

    read is O(log N) as in tree. And you can also
    afford a later keysort. Here is the bagof/3 choker
    with hash+keysort compared to tree:

    /* Dogelog Player 1.2.5, tree */
    ?- time(test3).
    % Zeit 6073 ms, GC 1 ms, Lips 5182931, Uhr 10.11.2024 00:58
    true.

    /* Dogelog Player 1.2.5, hash+keysort */
    ?- time(test4).
    % Zeit 3070 ms, GC 2 ms, Lips 9808736, Uhr 10.11.2024 00:58
    true.

    Quite amazing, if we compare to the traditional bagof/3:

    /* Trealla Prolog 2.59.17, keysort */
    ?- time(test).
    % Time elapsed 13.280s, 16158649 Inferences, 1.217 MLips
    true.

    Mild Shock schrieb:
    It all began with the bagof/3 choker:

    test :-
       bagof(X, N^(between(1,300,X), between(1,300,N),
          length(_,N)), _), fail; true.

    Which makes Prolog system tumble:

    /* SWI-Prolog 9.3.14 */
    ?- time(test).
    Action (h for help) ? abort
    % 468,739 inferences, 52.016 CPU in 53.069 seconds (98% CPU, 9012 Lips) Execution Aborted

    /* Scryer Prolog 0.9.4-201 */
    ?- time(test).
    ^C   % CPU time: 110.153s, 145_508_466 inferences
       error('$interrupt_thrown',repl/0).

    Its mostlikely the same old problem that was
    observed years ago, in that the canonicalization
    of variables before the keysort/2 creates long

    instantiation chains. It can be solved by adjusting
    the unification order. Here is a take in Dogelog Player:

    /* Dogelog Player 1.2.5 */
    ?- time(test).
    % Zeit 7405 ms, GC 21 ms, Lips 3962971, Uhr 10.11.2024 00:57
    true.



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sun Nov 10 12:42:04 2024
    From Newsgroup: comp.lang.prolog

    How did I solve the variant key problem,
    which is present in the bagof/3 choker? I
    went with numbervars/3 and unnumbervars/3.

    But most likely if tries are used for tabling,
    they can already do the same. I was looking
    a little bit at the trie_insert() C implementation

    used in SWI-Prolog distinct/1. It seems distinct/1
    can solve the variant key problem by means of
    trie_insert/2 alone, since for ordinary

    terms it uses a no-op:

    trieable(Term, ForTrie) :-
    acyclic_term(Term),
    term_attvars(Term, []),
    !,
    ForTrie = t(Term).

    Not sure what is needed to enumerate variant key,
    turn them back into ordinary terms together
    with the associated values. I am also using the

    nb_linkarg/3 trick for findall/3 inside bagof/3.
    So the values are basically these single linked
    lists. The same approach for bagof/3, is also

    suitable for aggregate/3.

    Mild Shock schrieb:
    But we can also do without term_variables/3 or
    term_variable/2.  don’ have tries in my system.
    But I recently introduced Okasaki tree, but it

    turned out that they are totally useless. What
    works better in my case was hash+keysort, as
    strange as it may sound.

    I believe it depends on the grouping factor.
    If there is a high grouping factor there is
    higher precentage of read from the grouping

    datastructure and than write into the
    grouping datastructure. So if read is only O(1)
    as in hash, you have better preformance than if

    read is O(log N) as in tree. And you can also
    afford a later keysort. Here is the bagof/3 choker
    with hash+keysort compared to tree:

    /* Dogelog Player 1.2.5, tree */
    ?- time(test3).
    % Zeit 6073 ms, GC 1 ms, Lips 5182931, Uhr 10.11.2024 00:58
    true.

    /* Dogelog Player 1.2.5, hash+keysort */
    ?- time(test4).
    % Zeit 3070 ms, GC 2 ms, Lips 9808736, Uhr 10.11.2024 00:58
    true.

    Quite amazing, if we compare to the traditional bagof/3:

    /* Trealla Prolog 2.59.17, keysort */
    ?- time(test).
    % Time elapsed 13.280s, 16158649 Inferences, 1.217 MLips
       true.

    Mild Shock schrieb:
    It all began with the bagof/3 choker:

    test :-
        bagof(X, N^(between(1,300,X), between(1,300,N),
           length(_,N)), _), fail; true.

    Which makes Prolog system tumble:

    /* SWI-Prolog 9.3.14 */
    ?- time(test).
    Action (h for help) ? abort
    % 468,739 inferences, 52.016 CPU in 53.069 seconds (98% CPU, 9012 Lips)
    Execution Aborted

    /* Scryer Prolog 0.9.4-201 */
    ?- time(test).
    ^C   % CPU time: 110.153s, 145_508_466 inferences
        error('$interrupt_thrown',repl/0).

    Its mostlikely the same old problem that was
    observed years ago, in that the canonicalization
    of variables before the keysort/2 creates long

    instantiation chains. It can be solved by adjusting
    the unification order. Here is a take in Dogelog Player:

    /* Dogelog Player 1.2.5 */
    ?- time(test).
    % Zeit 7405 ms, GC 21 ms, Lips 3962971, Uhr 10.11.2024 00:57
    true.




    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Tue Nov 12 16:30:48 2024
    From Newsgroup: comp.lang.prolog

    Concerning the input (xxx yyy zzz) the OP wrote:

    I would expect it to print zzz(xxx(yyy)).

    Where did he get this requirement from, he didn’t
    compare other Prolog systems, right? So it came from
    his applicationdomain. But what was his application

    domain? Ok, lets proceed to an example with multiple
    brakets. Lets make the Pascal “begin” “end” example,
    by replacing xxx and zzz by “begin” and “end”.

    I get this result:

    ?- member(X,[begin,end]), current_op(Y,Z,X).
    X = (begin), Y = 1100, Z = fy ;
    X = (end), Y = 1100, Z = yf.

    ?- X = (begin
    | x = 1;
    | y = 2;
    | begin
    | z = 3
    | end
    | end).
    X = (begin x=1;y=2;begin z=3 end end).

    But is the abstract parse term, the Prolog result useful?

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Tue Nov 12 16:32:44 2024
    From Newsgroup: comp.lang.prolog

    Here is the SWI-Prolog and the SICStus
    Prolog abstract parse term. This is the real
    nightmare of every computer science professor,

    who wants to use Prolog in a compiler
    construction course:

    /* SWI-Prolog 9.3.14 */
    end(end(begin(;(=(x,1),;(=(y,2),begin(=(z,3)))))))

    /* SICStus Prolog 4.9.0 */
    begin(;(=(x,1),;(=(y,2),begin(end(end(=(z,3)))))))

    On the other hand mostlikely the OP @horsh
    would expect:

    /* What the End-User wants */ end(begin(;(=(x,1),;(=(y,2),end(begin(=(z,3)))))))

    I think its impossible to do in any Prolog system,
    you would need a programming language with the
    possibility to do mixfix syntax definitions,

    like for example in Isabelle/HOL:

    (* Define the mixfix syntax for a Pascal-like block *)
    syntax
    "_begin_end" :: "'a ⇒ 'a" ("begin _ end")

    Or otherwise use DCG to write your own parser
    for the DSL at hand, that you want to parse.
    Since Prolog operators cannot model mixfix syntax,

    at least SWI-Prolog and SICStus Prolog fail,
    and I guess other Prolog systems fail as well.

    Mild Shock schrieb:
    Concerning the input (xxx yyy zzz) the OP wrote:

    I would expect it to print zzz(xxx(yyy)).

    Where did he get this requirement from, he didn’t
    compare other Prolog systems, right? So it came from
    his applicationdomain. But what was his application

    domain? Ok, lets proceed to an example with multiple
    brakets. Lets make the Pascal “begin” “end” example,
    by replacing xxx and zzz by “begin” and “end”.

    I get this result:

    ?- member(X,[begin,end]), current_op(Y,Z,X).
    X = (begin), Y = 1100, Z = fy ;
    X = (end), Y = 1100, Z = yf.

    ?- X = (begin
    |          x = 1;
    |          y = 2;
    |          begin
    |               z = 3
    |          end
    |       end).
    X = (begin x=1;y=2;begin z=3 end end).

    But is the abstract parse term, the Prolog result useful?


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Nov 14 05:14:13 2024
    From Newsgroup: comp.lang.prolog


    Lets cut through the thicket. There is no
    real world use case of a (fy 1 yf). Take again
    the Pascal “begin” “end” mixfix example.
    Typically we want to then go on and write

    for example a compiler:

    :- op(1100,fy,begin).
    :- op(1100,yf,end).

    compile((begin X end)) --> compile(X). %%% scoping omitted
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    The problem is the pattern (begin X end) will
    not work, if multiple (begin … end) are involved
    in the compile/1 call. You can try yourself, no

    Prolog system can do it:

    /* SWI-Prolog */
    ?- X = (begin
    x = 1;
    begin
    y = 2
    end
    end), compile(X, L, []).
    false.
    %%% expected L = [load(1),store(x),load(2),store(y)]

    /* SICStus Prolog */
    ?- X = (begin
    x = 1;
    begin
    y = 2
    end
    end), compile(X, L, []).
    no.
    %%% expected L = [load(1),store(x),load(2),store(y)]

    The reason is that the parser will join multiple yf,
    similarly it would join multiple fy. The parser will
    not follow a braket pattern. At least I don’t know
    any Prolog system that can do it.

    Mild Shock schrieb:
    Here is the SWI-Prolog and the SICStus
    Prolog abstract parse term. This is the real
    nightmare of every computer science professor,

    who wants to use Prolog in a compiler
    construction course:

    /* SWI-Prolog 9.3.14 */
    end(end(begin(;(=(x,1),;(=(y,2),begin(=(z,3)))))))

    /* SICStus Prolog 4.9.0 */
    begin(;(=(x,1),;(=(y,2),begin(end(end(=(z,3)))))))

    On the other hand mostlikely the OP @horsh
    would expect:

    /* What the End-User wants */ end(begin(;(=(x,1),;(=(y,2),end(begin(=(z,3)))))))

    I think its impossible to do in any Prolog system,
    you would need a programming language with the
    possibility to do mixfix syntax definitions,

    like for example in Isabelle/HOL:

    (* Define the mixfix syntax for a Pascal-like block *)
    syntax
      "_begin_end" :: "'a ⇒ 'a" ("begin _ end")

    Or otherwise use DCG to write your own parser
    for the DSL at hand, that you want to parse.
    Since Prolog operators cannot model mixfix syntax,

    at least SWI-Prolog and SICStus Prolog fail,
    and I guess other Prolog systems fail as well.

    Mild Shock schrieb:
    Concerning the input (xxx yyy zzz) the OP wrote:

    I would expect it to print zzz(xxx(yyy)).

    Where did he get this requirement from, he didn’t
    compare other Prolog systems, right? So it came from
    his applicationdomain. But what was his application

    domain? Ok, lets proceed to an example with multiple
    brakets. Lets make the Pascal “begin” “end” example,
    by replacing xxx and zzz by “begin” and “end”.

    I get this result:

    ?- member(X,[begin,end]), current_op(Y,Z,X).
    X = (begin), Y = 1100, Z = fy ;
    X = (end), Y = 1100, Z = yf.

    ?- X = (begin
    |          x = 1;
    |          y = 2;
    |          begin
    |               z = 3
    |          end
    |       end).
    X = (begin x=1;y=2;begin z=3 end end).

    But is the abstract parse term, the Prolog result useful?



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Nov 14 05:24:49 2024
    From Newsgroup: comp.lang.prolog


    So how will the computer science Professor help
    himself, and nevertheless show some compiler
    construction.

    If he lowers the expectation, he will use the curly
    braces, namely { .. }. This and the singleton list
    are practically the only braket syntaxes available

    in standard Prolog, that leave a term footprint. The
    normal parenthesis don’t leave any abstract parse tree.
    So this brave computer science Professor could go on:

    ompile({X}) --> compile(X). %%% scoping omitted
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    And he would then succeed in demonstrating a toy compiler:

    ?- X = {
    x = 1;
    {
    y = 2
    }
    }, compile(X, L, []).
    L = [load(1), store(x), load(2), store(y)].

    But this is very poor. It doesn’t allow for DSLs that
    use different braketing syntax. And the computer science
    professor will switch to Isabelle/HOL, since switching

    to Prolog DCG is too painful?

    Mild Shock schrieb:

    Lets cut through the thicket. There is no
    real world use case of a (fy 1 yf). Take again
    the Pascal “begin” “end” mixfix example.
    Typically we want to then go on and write

    for example a compiler:

    :- op(1100,fy,begin).
    :- op(1100,yf,end).

    compile((begin X end)) --> compile(X). %%% scoping omitted
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    The problem is the pattern (begin X end) will
    not work, if multiple (begin … end) are involved
    in the compile/1 call. You can try yourself, no

    Prolog system can do it:

    /* SWI-Prolog */
    ?- X = (begin
              x = 1;
              begin
                   y = 2
              end
           end), compile(X, L, []).
    false.
    %%% expected L = [load(1),store(x),load(2),store(y)]

    /* SICStus Prolog */
    ?- X = (begin
              x = 1;
              begin
                   y = 2
              end
           end), compile(X, L, []).
    no.
    %%% expected L = [load(1),store(x),load(2),store(y)]

    The reason is that the parser will join multiple yf,
    similarly it would join multiple fy. The parser will
    not follow a braket pattern. At least I don’t know
    any Prolog system that can do it.

    Mild Shock schrieb:
    Here is the SWI-Prolog and the SICStus
    Prolog abstract parse term. This is the real
    nightmare of every computer science professor,

    who wants to use Prolog in a compiler
    construction course:

    /* SWI-Prolog 9.3.14 */
    end(end(begin(;(=(x,1),;(=(y,2),begin(=(z,3)))))))

    /* SICStus Prolog 4.9.0 */
    begin(;(=(x,1),;(=(y,2),begin(end(end(=(z,3)))))))

    On the other hand mostlikely the OP @horsh
    would expect:

    /* What the End-User wants */
    end(begin(;(=(x,1),;(=(y,2),end(begin(=(z,3)))))))

    I think its impossible to do in any Prolog system,
    you would need a programming language with the
    possibility to do mixfix syntax definitions,

    like for example in Isabelle/HOL:

    (* Define the mixfix syntax for a Pascal-like block *)
    syntax
       "_begin_end" :: "'a ⇒ 'a" ("begin _ end")

    Or otherwise use DCG to write your own parser
    for the DSL at hand, that you want to parse.
    Since Prolog operators cannot model mixfix syntax,

    at least SWI-Prolog and SICStus Prolog fail,
    and I guess other Prolog systems fail as well.

    Mild Shock schrieb:
    Concerning the input (xxx yyy zzz) the OP wrote:

    I would expect it to print zzz(xxx(yyy)).

    Where did he get this requirement from, he didn’t
    compare other Prolog systems, right? So it came from
    his applicationdomain. But what was his application

    domain? Ok, lets proceed to an example with multiple
    brakets. Lets make the Pascal “begin” “end” example,
    by replacing xxx and zzz by “begin” and “end”.

    I get this result:

    ?- member(X,[begin,end]), current_op(Y,Z,X).
    X = (begin), Y = 1100, Z = fy ;
    X = (end), Y = 1100, Z = yf.

    ?- X = (begin
    |          x = 1;
    |          y = 2;
    |          begin
    |               z = 3
    |          end
    |       end).
    X = (begin x=1;y=2;begin z=3 end end).

    But is the abstract parse term, the Prolog result useful?




    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Thu Nov 14 21:21:50 2024
    From Newsgroup: comp.lang.prolog

    On 14/11/2024 05:14, Mild Shock wrote:

    Typically we want to then go on and write
    for example a compiler:

    :- op(1100,fy,begin).
    :- op(1100,yf,end).

    compile((begin X end)) --> compile(X). %%% scoping omitted
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    The problem is the pattern (begin X end) will
    not work, if multiple (begin … end) are involved
    in the compile/1 call. You can try yourself, no
    Prolog system can do it:

    /* SWI-Prolog */
    ?- X = (begin
              x = 1;
              begin
                   y = 2
              end
           end), compile(X, L, []).
    false.
    %%% expected L = [load(1),store(x),load(2),store(y)]
    <snip>

    This seems to do the trick:

    ```
    % SWI-Prolog 9.2.7

    :- op(1100, fy, begin).
    :- op(1100, yf, end).

    compile((begin XEnd)) --> compile(XEnd).
    compile((X end)) --> compile(X).
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    compile_t(X, L) :-
    X = (
    begin
    x = 1;
    begin
    y = 2
    end
    end
    ),
    compile(X, L, []).
    ```

    ```
    ?- compile_t(X, L).
    X = (begin x=1;begin y=2 end end),
    L = [load(1),store(x),load(2),store(y)].
    ```

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Nov 14 21:58:02 2024
    From Newsgroup: comp.lang.prolog

    Yes, maybe, it depends. You would
    need to fill in some logic for the
    block functionality, like opening

    and closing a table with variable
    names. And try it as such with a larger
    variety of example. Also compare whether

    it works for both SWI-Prolog and SICStus
    Prolog. What one can already see for sure,
    the compile is not extremly safe anymore.

    It would also accept non well formed
    input. Like you can call it with unbalanced
    begin end now, and the compile/1 clause

    pattern matching will not fail, and it
    will start producing some code:

    ?- compile((begin x=1 end end)).

    But maybe this is a minor problem. Another
    challenge is for example the Pascal if-then-else.
    Basically a mixfix with 3 holes.

    if _ then _ else _

    https://www.tutorialspoint.com/pascal/pascal_if_then_else_statement.htm

    Just like in the begin end case, where
    we can provide non-well formed input
    like (begin x=1 end end). Ordinary

    Prolog operators will again not provide
    the safety and versatility for writing rules.

    Julio Di Egidio schrieb:
    This seems to do the trick:

    ```
    % SWI-Prolog 9.2.7

    :- op(1100, fy, begin).
    :- op(1100, yf, end).

    compile((begin XEnd)) --> compile(XEnd).
    compile((X end)) --> compile(X).
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    compile_t(X, L) :-
        X = (
            begin
                x = 1;
                begin
                    y = 2
                end
            end
        ),
        compile(X, L, []).
    ```

    ```
    ?- compile_t(X, L).
    X = (begin x=1;begin y=2 end end),
    L = [load(1),store(x),load(2),store(y)].
    ```

    -Julio


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Nov 14 22:10:29 2024
    From Newsgroup: comp.lang.prolog

    This is also a rather frustrating case,
    you might run into the same problem when

    you would try doing if-then-else:

    ?- X = (begin x=1 end; y=2; begin z=3 end).
    ERROR: Syntax error: Operator priority clash

    Unparsable in both SWI-Prolog and SICStus
    Prolog. On the other hand using {}/1 works:

    ?- X = ({x=1}; y=2; {z=3}).
    X = ({x=1};y=2;{z=3}).

    Mild Shock schrieb:
    Yes, maybe, it depends. You would
    need to fill in some logic for the
    block functionality, like opening

    and closing a table with variable
    names. And try it as such with a larger
    variety of example. Also compare whether

    it works for both SWI-Prolog and SICStus
    Prolog. What one can already see for sure,
    the compile is not extremly safe anymore.

    It would also accept non well formed
    input. Like you can call it with unbalanced
    begin end now, and the compile/1 clause

    pattern matching will not fail, and it
    will start producing some code:

    ?- compile((begin x=1 end end)).

    But maybe this is a minor problem. Another
    challenge is for example the Pascal if-then-else.
    Basically a mixfix with 3 holes.

       if _ then _ else _

    https://www.tutorialspoint.com/pascal/pascal_if_then_else_statement.htm

    Just like in the begin end case, where
    we can provide non-well formed input
    like (begin x=1 end end). Ordinary

    Prolog operators will again not provide
    the safety and versatility for writing rules.

    Julio Di Egidio schrieb:
    This seems to do the trick:

    ```
    % SWI-Prolog 9.2.7

    :- op(1100, fy, begin).
    :- op(1100, yf, end).

    compile((begin XEnd)) --> compile(XEnd).
    compile((X end)) --> compile(X).
    compile((X;Y)) --> compile(X), compile(Y).
    compile((V=E)) --> [load(E),store(V)].

    compile_t(X, L) :-
         X = (
             begin
                 x = 1;
                 begin
                     y = 2
                 end
             end
         ),
         compile(X, L, []).
    ```

    ```
    ?- compile_t(X, L).
    X = (begin x=1;begin y=2 end end),
    L = [load(1),store(x),load(2),store(y)].
    ```

    -Julio



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Nov 14 22:30:11 2024
    From Newsgroup: comp.lang.prolog


    Ok, here is my minimal test case, to
    demonstrate that fy 2 yf has not much
    practical use. Irrespective how it is

    parsed. The test case is the computer
    science professor who wants to teach
    compiler construction, and defines a

    toy language that has among other things
    a Pascal begin end:

    :- op(1100, fy, begin).
    :- op(1100, yf, end).

    Neither SWI-Prolog nor SICStus Prolog can parse this:

    ?- X = (begin x=1 end; begin y=2 end).
    ERROR: Syntax error: Operator priority clash

    I am also not able to parse it in Dogelog
    Player, Trealla Prolog and Scryer Prolog.
    I guess it has to do that disjunction uses

    xfy mode. Mostlikely yfx mode would also not
    help? What would help if there were
    a yfy mode (sic!).


    Mild Shock schrieb:
    Concerning the input (xxx yyy zzz) the OP wrote:

    I would expect it to print zzz(xxx(yyy)).

    Where did he get this requirement from, he didn’t
    compare other Prolog systems, right? So it came from
    his applicationdomain. But what was his application

    domain? Ok, lets proceed to an example with multiple
    brakets. Lets make the Pascal “begin” “end” example,
    by replacing xxx and zzz by “begin” and “end”.

    I get this result:

    ?- member(X,[begin,end]), current_op(Y,Z,X).
    X = (begin), Y = 1100, Z = fy ;
    X = (end), Y = 1100, Z = yf.

    ?- X = (begin
    |          x = 1;
    |          y = 2;
    |          begin
    |               z = 3
    |          end
    |       end).
    X = (begin x=1;y=2;begin z=3 end end).

    But is the abstract parse term, the Prolog result useful?


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Fri Nov 15 15:42:05 2024
    From Newsgroup: comp.lang.prolog

    On 14/11/2024 21:58, Mild Shock wrote:

    Yes, maybe, it depends. You would
    need to fill in some logic for the
    block functionality, like opening

    Yes, the problem is a conflict in block scoping syntax, but it is only a problem with a shallow embedding *and* expecting to stay 100% faithful
    to the object language syntax.

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114