Do you known "Prolog"?
"Prolog" is a programming language that was developed in 1972.
Prolog is not "object-oriented programming language", not "functional programming language".
It is categorized into "logic programming language".
Interestingly, in Prolog programming, programmers don't write operation sequences.
Instead, they write "facts" and "rules" as a Prolog code.
human(socrates).
mortal(X) :- human(X).
After the Prolog runtime process the code, the user can ask the Prolog runtime to a query.
?- mortal(X).
Then the Prolog runtime tries to find solutions to the query, and the runtime tells us solutions if they are found.
X = socrates
I feel Prolog is a little bit strange and funny.
Before I know Prolog, I could not think that create a PC application written by only logical code, not procedure code.
Can I create Single Page Web App with Prolog?
By the way, I have learned "Blazor" which is technology to create a Single Page Web Application (a.k.a "SPA") with C#.
Blazor allows us to run .NET MSIL code on a web browser's WebAssembly engine.
And I know there is the Prolog interpreter "C#Prolog" written by C#.
So, one day, I came up with the idea that by combining Blazor and C# Prolog, I could create a SPA in Prolog.
This Year-end and New Year vacations (2020-2021), I tried to realize that idea, and I did it finally.
"Spprologa" - the library to make a SPA with Prolog
I published a new .NET library "Spprologa".
"Spprologa" allows you to make a SPA with Prolog.
"Spprologa" means the initials of "Single Page Prolog Application".
Maybe as you know, due to this library built on Blazor and C#Prolog, all of the Prolog codes are running inside of the Web browser, not the server process.
The Prolog codes are interpreted by the interpreter (C#Prolog) that runs on the Web browser's WebAssembly engine, not transpiled to JavaScript.
This means "Spprologa" apps can be hosted on any HTTP servers that can serve at least static contents, such as GitHub Pages, Firebase, Netlify, Azure Static Web, etc.
You can see the live demo site (following URL) which deployed to GitHub Pages.
Let's programming the "Spprologa" app
Prerequires
"Spprologa" is based on Blazor, therefore .NET SDK v.5.0.101 or later is required to develop a "Spprologa" application.
To install .NET SDK into your PC or Mac, please see also the following URL.
And I recommend installing the "Spprologa" project template by the following command, before starting "Spprologa" application programming.
$ dotnet new -i Spprologa.Templates::0.0.1-preview.4.0.0.0
Create a new "Spprologa" app project , and run it.
Once the installation of the project template is complete, you can create a new "Spprologa" application project in the current folder by the dotnet new
command.
$ dotnet new spprologa
After creating a new "Spprologa" application project, executing the following command starts building and running the app. And the application's URL will be opened by a default Web browser automatically.
$ dotnet watch run
Publish the project
If you want to deploy the app to a Web server, execute the dotnet publish
command like this:
$ dotnet publish -c:Release -o path/to/output
After executing the command above, all of the contents will be generated that are required to running the app in the path/to/output/wwwroot
folder.
Feature concepts
"Spprologa" application programming is based on 5 features as following.
1. *.razor.prolog
files in the project are consulted automatically.
% /Pages/Foo.razor.prolog
% This Prolog code file will be consulted only once
% when the "Foo.razor" component is first rendering.
input(name, "").
bird("swallow", canfly).
bird("penguin", canswim).
canfly(Name) :- bird(Name, canfly).
classify(Name, "can fly") :- canfly(Name).
classify(Name, "is bird, but can't fly.") :- bird(Name, _).
classify(_, "isn't bird.").
check :-
input(name, Name), classify(Name, Message),
retractall(message(_, _)), asserta(message(Name, Message)).
2. Bind result of a query to DOM contents.
Use @query("...")
to retrieve a variable value inside a solution of a query which is specified as an argument, and render it as the HTML contents.
<!-- /Pages/Foo.razor -->
...
<span>
<!-- 👇 This code will render "swallow". -->
@query("canfly(Name)")
</span>
3. Bind input to a fact.
Use @fact("...")
to two way bind to an input
element.
<!-- /Pages/Foo.razor -->
...
<input @bind='@fact("input(name, {0})").as_string' />
If the user inputs the text "gopher" into the input
element above, then all input(name, _)
facts will be retracted, and instead the fact input(name, "gopher")
will be asserted.
4. Bind an action to a query.
Use @then("...")
to make the query will be called when an event is fired.
<!-- /Pages/Foo.razor -->
...
<button @onclick='@then("check")'>Check</button>
If the user clicks the button above, the query check
will be called.
5. List up facts.
Use the <Case>
component to retrieve all solutions of a query and render values of each solution to HTML contents.
<!-- /Pages/Foo.razor -->
...
<ul>
<Case Query="bird(Name, Ability)">
<li>@context["Name"] - @context["Ability"]</li>
</Case>
<ul>
The above code will render to HTML as follow:
<ul>
<li>swallow - canflay</li>
<li>penguin - cannotflay</li>
</ul>
What can "Spprologa" apps do?
As you know from my live demo site, I created a "coloring map" solver.
The core code to resolve it is just the following.
% define that what colors are there.
color(red).
color(green).
color(blue).
color(yellow).
% The implementation of the map coloring.
color_of_map(Alabama, Mississippi, Georgia, Tennessee, Florida) :-
color(Alabama), color(Mississippi), color(Georgia), color(Tennessee), color(Florida),
Tennessee \= Mississippi,
Tennessee \= Alabama,
Tennessee \= Georgia,
Mississippi \= Alabama,
Alabama \= Georgia,
Alabama \= Florida,
Georgia \= Florida.
And I also created "Sudoku" (but this version 4 x 4 cells) solver.
The core code to the solver is just the following.
sudoku(Puzzle, Solution) :-
Solution = Puzzle,
Puzzle = [
S11, S12, S13, S14,
S21, S22, S23, S24,
S31, S32, S33, S34,
S41, S42, S43, S44
],
NUMBERS = [1,2,3,4],
% rows
permutation(NUMBERS, [S11, S12, S13, S14]),
permutation(NUMBERS, [S21, S22, S23, S24]),
permutation(NUMBERS, [S31, S32, S33, S34]),
permutation(NUMBERS, [S41, S42, S43, S44]),
% columns
permutation(NUMBERS, [S11, S21, S31, S41]),
permutation(NUMBERS, [S12, S22, S32, S42]),
permutation(NUMBERS, [S13, S23, S33, S43]),
permutation(NUMBERS, [S14, S24, S34, S44]),
% square
permutation(NUMBERS, [S11, S12, S21, S22]),
permutation(NUMBERS, [S31, S32, S41, S42]),
permutation(NUMBERS, [S13, S14, S23, S24]),
permutation(NUMBERS, [S33, S34, S43, S44]).
Interestingly, I didn't program any algorithms to solve them.
Instead, I only wrote constraints and rules of those puzzles as a Prolog code.
I think this is the wonder and charm of Prolog programming.
Notice: This is just "Proof of Concept"
"Spprologa" has been started by just only my interest that the "Prolog" can make a single page web app or not.
Therefore, this library may be abandoned after I lose interest in it.
However, this project is distributed under the Mozilla Public License.
So anybody can fork and can continue this project freely anytime, and I will strongly welcome it. 👍
Have fun with Prolog programming!
Top comments (1)
Hi,
Excellent article. I had query around one of your github projects - github.com/jsakamoto/BlazorMinimum...
Any pointers on how to create a project template for Blazor. Any tutorial links would be really helpful.