scryer-prolog: Rebis: HTTP server no longer works
For example, with server.pl comprising:
:- use_module(library(http/http_server)).
run(Port) :-
http_listen(Port, [get(/, request_response)]).
request_response(_, Response) :-
http_status_code(Response, 200),
http_body(Response, text("Hello!")).
and running:
?- run(6080).
and then accessing http://localhost:6080/, I get as output:
Listening at port 6080 2021-02-17 (22:44:40) get / caught: error(existence_error(procedure,request_response/2),request_response/2)
This needs to be resolved maybe by taking the module into account. A meta_predicate declaration could maybe help, though it is unclear how exactly. This directive makes the compiler add a suitable module prefix to all predicate arguments that are declared as meta-goals.
@aarroyoc, I would greatly appreciate if you could take a look at this issue. Thank you a lot!
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (12 by maintainers)
I’ve used your ideas in #834 . Thank you so much!
It appears all that’s needed is:
:- meta_predicate http_listen(?, 2). http_listen(Port, Module:Handlers0) :- maplist(module_qualification(Module), Handlers0, Handlers), http_listen_(Port, Handlers). module_qualification(M, H0, H) :- H0 =.. [Method, Path, Goal], H =.. [Method, Path, M:Goal].Due to the
meta_predicate/1declaration, we know that theModule:qualification will be present, the compiler will add it to the second argument.The only problem with this is that, as you noted, the
meta_predicate/1declaration strictly speaking does not fit this situation. We are only using it to make the compiler add the module prefix, and at least we can use it as a workaround for now. There may be a more elegant solution to this that correctly models the situation. Expressing the situation more correctly could become more useful in the future when cross-referencers and other tools use themeta_predicate/1declarations to really reason about the Prolog code, analysing which predicates are invoked, finding missing definitions etc.With this change, it also works:
But it doesn’t generalize
meta_predicate/1.I understand what @triska is proposing but now we have two problems: find a sensible generalization and implement it. TBH for most of the time, I thought that what
meta_predicate/1does was already done automatically (like in most languages with first-class functions) but I understand now why it is like this, the need to be able to differentiate goals from other terms (to which this transformation shouldn’t be done).I agree that it may be generalizable enough to look for a new solution. To be more constructive, this is the first thing that pops into my mind, though I don’t like that it doesn’t resemble Prolog too much.
:- meta_predicate http_listen (?, [_(?, 2)]).This will look tell the compiler that the second argument is a list, which contains terms (any functor marked with _) and the second argument of each term is a goal.Yes, completely correct.
I propose to use this opportunity to try to find a sensible and general approach to solve such issues instead of implementing an ad hoc change that is also not backwards compatible.
But it’s
get(/, Goal)andget/2isn’t a predicate. There is also the case of specifying a predicate from another module after importing it.Yes, that works with and without the PR
Another way around is
get(/, user:request_response)orget(/, server:request_response)if the module isserver.I have a fix here: https://github.com/mthom/scryer-prolog/pull/830
I’ll look into it but I’m not too sure how to approach this