Simple Web, do I use a reply naming convention?

76 views
Skip to first unread message

Paul Brown

unread,
Nov 10, 2018, 5:20:35 AM11/10/18
to SWI-Prolog
I've been developing a pack called Simple Web, it's an opinionated micro-framework aimed at lowering the barrier to beginning web development using SWI-Prolog. Maybe I'm biased, but I do find it very easy to work with! As such, a large part of it's work is simplifying imports and providing the most commonly used predicates to you. This brings me to my current debate, there is an inconsistency in some of these predicate naming conventions, between `http_reply_X` and `reply_X`. I am thinking it would be wise for me to hide this inconsistency from a beginner so that all reply predicates would be `reply_X`:

* `reply_html`
* `reply_template`
* `reply_file`
* `reply_json_dict`
* `reply_404`
* `reply_redirect`

My concern is that might cause some confusion for developers when they wish to delve deeper into SWI-Prolog for web development, although it would be documented. What do you think?

If you'd like to know more about Simple Web, you can find the repository with README here: https://gitlab.com/PaulBrownMagic/simple_web
Note that it's not at version 1.0 yet, it's still subject to breaking changes such as implementing this debated naming convention.

I've also put together a repository of examples, including using it as an API, with Simple Template, and with Vue,js: https://gitlab.com/PaulBrownMagic/simple_web_examples/

Regarding extra features, it is a micro-framework, so it will not provide much, just the basics for a web server. I expect that other packs that work with it will provide these features, so you could create Simple Vue, Simple Bootstrap, Simple Pengines, Simple Forms, Simple Sessions, Simple Security, Simple RDF, Simple Logging, Simple Whatever You Want. I called this Simple Web because it was designed to work with Simple Templates, if you design a pack to work with it, then just call it Simple, and make sure it is super simple! But again, beware we're not at version 1.0 yet.

Raivo Laanemets

unread,
Nov 10, 2018, 7:21:29 AM11/10/18
to SWI-Prolog
I have worked a lot with web application in SWI. Not only you have to have a naming convention but
also calling convention. I believe that some of those predicates use exceptions as part of control flow
so that code reply_something(X), log_replied(X) won't work as reply_something throws as part of
its normal execution. This can be an interesting surprise. You might want to normalize to explicit
throw(http_reply()) in your code instead of using the predicates above. It's mentioned somewhere
in the manual but is hard to find.

I do not remember why Simple Template was named as it is. The main idea was to use an HTML editor
to edit the HTML templates instead of using Prolog terms. The Simple Template pack is more-less OK
for that but it lacks some useful abstractions like blocks/slots.

Regarding HTML templates I have had some thoughts about going with server-side rendering of Vue/React
through a combined Prolog/JavaScript runtime possibly using Duktape. It needs to pull data from Prolog through
FLI and I have worked with FLI couple of times. The SWI WebAssembly port needs exactly the same interface.

Considering a framework development the best way is to extract pieces from a working application. Developing
in isolation might not be good.

Paul Brown

unread,
Nov 10, 2018, 12:13:22 PM11/10/18
to SWI-Prolog
Tere Raivo! I will be visiting Estonia for Christmas, especially looking forward to seeing the Old Town in Tallinn during winter.

I haven't worked with web applications enough in SWI to understand reply_something(X), log_replied(X) vs throw(http_reply()). If you could expand more, please do email me.

I know Simple Template lacks some useful features, but it's still the best we have. I am secretly hoping that Simple Web will attract enough attention that someone might try to develop these features for Simple Template. I'm afraid templating is not my area of expertise, I looked over the code but have no idea about how to go about implementing these features. Currently I work around the issues by rendering a base template with dynamic includes for blocks. I think I'll add an example of this to that repository.

To support the development of Simple Web, I am eating my own dog food. I am using it firstly in an "electron" style desktop application, with Vue.js. I am also porting my personal website over from Python/Flask to SWI-Prolog, just trying to get my head around SWI-Prolog's RDF support to get that done. Plus I'll have to change hosts as my current one only supports Python web applications. Plus, developing the examples helps, I've found one bug that way and added one feature I discovered that I wanted.

Paul Brown

unread,
Nov 10, 2018, 6:36:44 PM11/10/18
to SWI-Prolog
I made the example showing how I extend a base template in Simple Template, using a Bootstrap base:

I've also upgraded Simple Web to 0.2.0, which includes the changes to the naming convention, but also allows you to declare your working directory so you can run it from anywhere, and I've added a location predicate similar to `http:location/3`, but I really wanted a `location/2` option as well.

Paul Brown

unread,
Nov 11, 2018, 7:39:55 PM11/11/18
to SWI-Prolog
To demonstrate how Simple Web can be extended and because it's useful, I've turned the Bootstrap Templates example into a pack. You can now get the bootstrap base and static files by including installing, and using `pack(simple_bootstrap)'.

```
:- use_module(library(sw/simple_web)).
:- use_module(library(sw/simple_bootstrap)).

sw:route('/', _Request) :-
    reply_template(bootstrap_base, _{}).
```

Raivo Laanemets

unread,
Nov 15, 2018, 6:02:57 AM11/15/18
to SWI-Prolog
Welcome to Estonia. If we are lucky we get some snow during Christmas, not the usual rainy muddy mess :)

In that code example I meant a HTTP handler like this:

handle_request(Request):-
 do_something
(Request),
 http_redirect
(moved, '/something_else', Request),
 log
('Did something and redirected user').

In this handler the last line with the log predicate call is not executed as http_redirect/3 throws an exception.
Various http_ predicates in http_dispatch all use exceptions to implement what they do. This can be an
interesting surprise as some of the code does not execute yet you get no error. I once debugged it 2 hours.

I'm thinking about implementing blocks for simple_template. The vdom engine I built can be used for
templates as well and it supports blocks through the concept of components which are represented
by custom HTML elements and they pass around the children elements.

Paul Brown

unread,
Nov 15, 2018, 6:20:37 AM11/15/18
to SWI-Prolog
Ah, I see!

Hmm, seems like a quite a challenge. Maybe if it's in the route predicate the clause can be inspected, or I've got proxies to http_redirect/3 and http_404/2, so could hold off unifying these until a log term is ground.

```prolog
sw:route('/', Request, log(Something)) :-
    do_something(Request),
    reply_redirect(moved, '/something_else', Request),
    Something = 'Did something and redirected user'.
```

I remember playing around with delayed unification for negation, I'll see if there's something there that can help. I would be very happy if you chose to add blocks to Simple Template!

Jan Wielemaker

unread,
Nov 15, 2018, 6:24:17 AM11/15/18
to Raivo Laanemets, SWI-Prolog
On 15/11/2018 12:02, Raivo Laanemets wrote:
> Welcome to Estonia. If we are lucky we get some snow during Christmas,
> not the usual rainy muddy mess :)

Like the Netherlands, only there is the probability of a white
Christmas really low :(
> In that code example I meant a HTTP handler like this:
>
> handle_request(Request):-
> do_something(Request),
> http_redirect(moved,'/something_else',Request),
> log('Did something and redirected user').
> |
>
> In this handler the last line with the log predicate call is not
> executed as http_redirect/3 throws an exception.
> Various http_ predicates in http_dispatch all use exceptions to
> implement what they do. This can be an
> interesting surprise as some of the code does not execute yet you get no
> error. I once debugged it 2 hours.

For a long time that was the only way it could due to the way the
cgi-stream was implemented that could only handle 200 replies. Since
there are many non-error replies that are not 200 and have content the
cgi-stream has been extended a lot. You can now simply write

Status: 302
Location: /go/here

as part of the header and the system will reply using a redirect
(not tested, details may matter but it surely can work).

I'm surely in favour of a proper redesign of the web server library.
There are too many layers of incremental patches to accomodate new
standards and practices as well as support for outdated stuff such
as not using threads.

Ideally, I guess the existing low-level support should be rationalised
and then it should accomodate multiple high level APIs including the
current one for compatibility.

Cheers --- Jan

> I'm thinking about implementing blocks for simple_template. The vdom
> engine I built can be used for
> templates as well and it supports blocks through the concept of
> components which are represented
> by custom HTML elements and they pass around the children elements.

Also note that the HTML quasi quotations can be used for templating,
e.g.

{|html(Text)||<div class="myclass">Text</div>|}

AFAIK, and attribute or content that matches one of the qq arguments is
replaced. Not saying that is ideal, but quasi quotations may be part of
the puzzle.



> On Saturday, November 10, 2018 at 7:13:22 PM UTC+2, Paul Brown wrote:
>
> Tere Raivo! I will be visiting Estonia for Christmas, especially
> looking forward to seeing the Old Town in Tallinn during winter.
>
> I haven't worked with web applications enough in SWI to understand
> reply_something(X), log_replied(X) vs throw(http_reply()). If you
> could expand more, please do email me.
>
> I know Simple Template lacks some useful features, but it's still
> the best we have. I am secretly hoping that Simple Web will attract
> enough attention that someone might try to develop these features
> for Simple Template. I'm afraid templating is not my area of
> expertise, I looked over the code but have no idea about how to go
> about implementing these features. Currently I work around the
> issues by rendering a base template with dynamic includes for
> blocks. I think I'll add an example of this to that repository.
>
> To support the development of Simple Web, I am eating my own dog
> food. I am using it firstly in an "electron" style desktop
> application, with Vue.js. I am also porting my personal website over
> from Python/Flask to SWI-Prolog, just trying to get my head around
> SWI-Prolog's RDF support to get that done. Plus I'll have to change
> hosts as my current one only supports Python web applications. Plus,
> developing the examples helps, I've found one bug that way and added
> one feature I discovered that I wanted.
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/swi-prolog.
> For more options, visit https://groups.google.com/d/optout.

Paulo Moura

unread,
Nov 15, 2018, 6:27:13 AM11/15/18
to Paul Brown, SWI-Prolog
Hi Paul,

You may find some inspiration in webtalk by Sando George:

https://github.com/sandogeorge/webtalk

Cheers,
Paulo
-----------------------------------------------------------------
Paulo Moura
Logtalk developer



Raivo Laanemets

unread,
Nov 15, 2018, 2:40:48 PM11/15/18
to SWI-Prolog
I added an implementation of blocks to simple_template:

Blocks are defined by files, similar to includes. Scoping rules
are the same except for passed-down content for which it is lexical
with respect to the block-using template.

One of the examples is page layout. I see tomorrow if I can publish
a new version of the pack. It's in the blocks branch. Some of my tests need reworking
before I can publish.

Vue/W3C component-like multi-slot blocks could be added as well although
I have not seen much usage for them in practical programming. The head
css/js case has been always done using array of extra js/css files and the
navigation case has been done using the 'menu' variable/property that hilights
the active page.

On Thursday, November 15, 2018 at 1:20:37 PM UTC+2, Paul Brown wrote:
Ah, I see!

Raivo Laanemets

unread,
Nov 15, 2018, 2:55:14 PM11/15/18
to SWI-Prolog
I explored quasi quotations some time ago. This would be a nice way to embed a
templating language. However, to get syntax highlighting, editor/ide's syntax definition
files need to be modified and that's sometimes quite hard.

Putting a template into a separate file that mostly is HTML solved this problem.

html//1 solves this by representing HTML as Prolog terms. This is good too once
you get used to these terms.

Jan Wielemaker

unread,
Nov 15, 2018, 3:39:55 PM11/15/18
to Raivo Laanemets, SWI-Prolog
On 15/11/2018 20:55, Raivo Laanemets wrote:
> I explored quasi quotations some time ago. This would be a nice way
> to embed a templating language. However, to get syntax highlighting,
> editor/ide's syntax definition files need to be modified and that's
> sometimes quite hard.

That is indeed a problem. There are some editors that can deal with
scoped highlighting of embedded languages. I would guess that support
for this will improve over time as many people consider syntax
highlighting a requirement and embedding languages is not uncommon.

> Putting a template into a separate file that mostly is HTML solved
> this problem.

True. For larger templates it is also completely fine and generally
desirable. For many small templates it is not so nice.

> html//1 solves this by representing HTML as Prolog terms. This is
> good too once you get used to these terms.

I think it is great for generating complicated pages with almost only
generated content, especially if different pages share elements because
reusing is trivially reusing grammar rules. It is poor for mostly fixed
pages with only fragments of dynamic content. There is Richard O'Keefe's
PWP for that, but I don't like specifying Prolog code in XML very much.

As more and more pages tend to use client side scripting this entire
problem vanishes as the server merely returns a JSON object. Of course,
if we run Prolog in the browser it comes back!

I'm afraid there is not one ideal way. That is fine as long as the
alternatives can live together.

Cheers --- Jan

> On Thursday, November 15, 2018 at 1:24:17 PM UTC+2, Jan Wielemaker
> wrote:
>
> Also note that the HTML quasi quotations can be used for templating,
> e.g.
>
> {|html(Text)||<div class="myclass">Text</div>|}
>
> AFAIK, and attribute or content that matches one of the qq arguments
> is replaced. Not saying that is ideal, but quasi quotations may be
> part of the puzzle.
>

Raivo Laanemets

unread,
Nov 19, 2018, 12:52:55 PM11/19/18
to SWI-Prolog
I republished the simple_template pack with this new feature. I hope it
now reduces verbosity from wrapping and layout use cases.

Paul Brown

unread,
Nov 21, 2018, 2:29:46 PM11/21/18
to SWI-Prolog
Checked out the blocks update, looks nice! I'll see about updating some of my examples to include it. Thanks for the update!
Reply all
Reply to author
Forward
0 new messages