How to save particular solutions in the REPL

Hello,

I would like to choose and save some of the solutions a predicate/query returns while ignoring all the others. I wonder what would be a straight forward solution for this.

Well, I could create a web interface or export as CSV and import choosen records back…

The next best solution seems to be writing my own REPL for this, but I wonder if there is something like a hook for the standard REPL:

Currently I can navigate through the solutions hitting keys “n” or “a” and print with “p”; and with “t S” I even can save a goal. (Unfortunately with “t S u a” I get some kind of crash with infinite back trace output - maybe a bug?)

But is there e.g. an option like adding a “s” key which saves the current solution for later use and then proceed with “n” as usual?

Kinde regards,
Wolfram.

Interesting. What do you want to do with the saved result, notably how do you envision to access them? Note that the toplevel result is a rather complex beast that consists of the variable bindings, but also pending constraints, residual goals, etc. In theory we could save that using a dict saved in the recorded DB.

I guess you already figured out that you can access the last toplevel variable binding using $Var?

I’m looking up translations in a dictionary by matching with isub, So far I iteratively filtered out for each word the 20 best matches while asserting and printing them to the screen with a letter a…z and afterwards asserted those which are fitting (using my eyes and brain) typing those letters to a predicate which I persist into a file. I redefined operators ? an & for this, so my workflow was:

?- ?<search>.
a..
b..
c..
...
t..
.

?- &adf. % saves solutions a d and f

But now I added more information to make better choices resulting in three screens filled before picking my solutions. This causes a lot of scrolling back and force - I don’t have a straight forward workflow anymore. Maybe buying a big screen is the best solution, but we are coders… :slight_smile:

So I thought about making a webpage showing the solutions with checkboxes and a button to write results back. But than I thought it should be a common usecase to pick specific solutions, and this should be possible without creating a GUI first, right?

With $Var you mean like in numbervars/3? But than I have to stop further searching for solutions first!? I thought it should work somehow like with the pidgeons in cinderella picking the good solutions one by one while skipping all the others till I have enough in my pot… than advancing to the next word.

I also could iterate using call_nths, stop after every solution and add it by some p. for pick, than hitting the up arrow, searching the next solution, but this seems a bit odd to me and also slows down the picking process.

Kind regards,
Wolfram.

There is a hook expand_answer/2 but I think I cannot control it with a key to either have a side effect or not, right?

I could maybe write out my three screens of solution candidates to a file which I open in a window which autoupdates on changes (VSC could do this). Than I don’t have to scroll in my Prolog window and could write my some letters there and commit. - bit easier than rewrite the REPL.

Regards,
Wolfram.

I don’t think there is anything that stops you for prompting the user.

I do think that the use case is too specific. If I had to do a lot of this I’d probably write a little web interface. The choice for how to present the answers and select the right ones as quickly as possible is probably critical. Possibly a terminal interaction will do as well, but that too is easy enough to write and probably more friendly that something generic.

No. After some query binds e.g. X to some term, you can use $X in subsequent toplevel queries which will be replaced by the term X was (last) bound to.

I do think that the use case is too specific.

Maybe at some point it could be interesting having an additional custom action in this list, which could be defined by a user hook:

Possible actions:
  ; (n,r,space,TAB): redo              | t:         trace&redo
  *:                 show choicepoint  | c (a,RET): stop
  w:                 write             | p:         print
  b:                 break             | h (?):     help

But according to your suggestions I will try to solve my particular usecase with an interaction loop, something like this could work:

dialog :-
    repeat, (
        solution(P),
        get_single_char(K),
        format('key ~w~n',K),
        (
            K = 0'q, %quit
            true
            ;
            (
                % save solution
                K = 0's,
                save(P)
                ;
                % goto next solution
                memberchk(K,[0'n,32,13])
                ;
                writeln('invalid key')
            ),
            fail
        )
    ),!.

solution(P) :-
    member(P,[a,b,c,d,e,f,g,h,u,j]),
    format('solution ~w~n',P).

save(P) :-
    format('saving ~w...~n',P).

If it is to limited I will try the webpage solution afterwards, should not be too difficult also.

Thanks for your suggestions,
Wolfram.

That is indeed also one of my thoughts. That would probably imply to make write_bindings2/4 in boot/toplevel.pl hookable. Not very easy to do in a nice stable way though. The REPL and its interaction has changed quite a few times and often this required some redesign in these predicates to get the right information at the right place.

Surely there is room to improve this code. E.g. have a layer on top of answer_respons/3 (and fix the spelling :slight_smile: ) there that separates interpreting the typed key from the command to execute, making it easier to add commands and generate the required help automatically. I’ll leave that to anyone interested enough :slight_smile: