xTurtle, is there any interest to make an executable stack with incorporat​ed SPARQL ?

Hi all,

Not sure this is the good place to talk about it, the idea exposed
below mixes turtle and SPARQL, so
I suppose it can fit here..

I had an idea some times ago but while some standards are being
discussed now within w3c, i though
it can be the moment to tell about. Perhaps its a very
silly/stupid/unsuitable idea or a way to do it, that i don't know,
already exists but i need to expose it at least to have your feed back
in order to forget it now if needed, not loosing
anymore my time on it.. ;)

The general idea is made of :
- Allowing SPARQL queries to be embedded into turtle syntax (do not
beat me for the moment, wait a bit.. :) )
- Building a processor able to parse and execute this kind of new
turtle with a standard, extensible library

The name could be xTurtle for instance, as "eXecutable Turtle",
exported as .xttl files and application/x-turtle.

The whole idea is then to allow sharing of executable programs within
triple-stores and linked-data.
It can offer very interesting native properties as easier code sharing
and re-use over the web, link data
and code together in a unique dataset or in separate datasets, can
offers a direct API for non websem-aware users for use in their
web apps, etc..

The sample below is a very early and basic piece of code using some
concepts i though about. The canvas, very useless, is the following :
- the user enters 10 numbers from the command line
- the program know all the artists with the age 42
- the program will then search on a SPARQL endpoint all musical
artists for entered ages different than 42
- the results and log lines will be stored on a 'log.txt' file

This sample use a local filesystem and the standard input, so it is
certainly not the good one to demonstrate what could be done
on a web environment but i think i shows the general principles..

===============================================================================

PREFIX :  <http://xturtle.com/core/0.1/#>
PREFIX loop: <http://xturtle.com/core/0.1/loop/#>
PREFIX ask:  <http://xturtle.com/core/0.1/ask/#>
PREFIX io:  <http://xturtle.com/lib/io/0.1/#>
PREFIX db:  <http://xturtle.com/lib/db/0.1/#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX my:  <#>

my:main a :Program;
 :header my:header {
  :id  "first_prog";
  :name "My First xSPARQL program";
  :author <http://mglcel.fr/>
 };
 :args my:_knownAge;
 :body :states {
  my:file a io:File;
   io:filename "log.txt";
   io:mode  io:writeable.

  my:numbers :selects SELECT ?line FROM io:stdin WHERE {
   ?line a  io:line;
     :cast xsd:integer.
  } LIMIT 10.

  my:list a  :List.
  ASK { my:numbers :lt my:_knownAge }
   :ontrue :states {
    io:stdout io:print "I already know all artists with age ", my:_knownAge.
    my:file io:print  "known artist".
   };
   :onfalse :states {
    io:stdout io:print "ok, a new data to retrieve is given"..
    my:file io:print "unknown artist with age", my:var.
    my:list :add  ask:subject.
   }.

  my:db a  db:SparqlEndpoint;
    db:url "http://my.db/endpoint".

  my:artists :constructs CONSTRUCT {
   ?artist  a   mo:MusicalArtist;
      foaf:age ?age;
      foaf:name ?name.
  }
  FROM my:db
  WHERE {
   ?artist  a   mo:MusicalArtist;
      foaf:age ?age;
      foaf:name ?name.
   FILTER( ?age IN my:list. ).
  }.

  my:results :selects SELECT ?name, ?age
  FROM my:artists
  WHERE {
   ?artist  foaf:age ?age;
      foaf:name ?name.
  }.

  my:results :loop :states {
   my:file  io:print "artist ", loop:name, " is aged ", loop:age.
  }.

 }

:context :call my:main :setarg my:_knownAge :value 42.

===============================================================================

Lets explain :

-------------------------------------------------------------------------------
PREFIX :  <http://xturtle.com/core/0.1/#>
PREFIX loop: <http://xturtle.com/core/0.1/loop/#>
PREFIX ask:  <http://xturtle.com/core/0.1/ask/#>
PREFIX io:  <http://xturtle.com/lib/io/0.1/#>
PREFIX db:  <http://xturtle.com/lib/db/0.1/#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX my:  <#>
-------------------------------------------------------------------------------
Loads the core language, the standard io and db libraries.
Perhaps some simplifications could be done, with implicit load of core prefixes
for instance.. (':', ':ask' and ':loop')
Adds foaf namespace for use in some queries.
Adds the my: prefix as of the current document.

-------------------------------------------------------------------------------
my:main a :Program;
 :header my:header {
  :id  "first_prog";
  :name "My First xSPARQL program";
  :author <http://mglcel.fr/>
 };
 :args my:_knownAge;
 :body :states {
   ....
 }
-------------------------------------------------------------------------------
The general format for a program or a function, allowing to specify an optional
header and some parameters.
Then the body as a set of statements (:states subClass of rdf:Seq for instance).

Some statements can then be automagically added by the interpreter, like :
- my:header a :ProgramHeader.
- my:_knownAge a :ProgramParameter.

Lets enter into the body :

-------------------------------------------------------------------------------
  my:file a io:File;
   io:filename "log.txt";
   io:mode  io:writeable.
-------------------------------------------------------------------------------
A local file named 'log.txt' is opened on local filesystem (or we can
imagine a way
to remotely open files on a web virtual fs..). This instance of
io:File is named my:file.

-------------------------------------------------------------------------------
  my:numbers :selects SELECT ?line FROM io:stdin WHERE {
   ?line a  io:line;
     :cast xsd:integer.
  } LIMIT 10.
-------------------------------------------------------------------------------
":selects" accepts as object a SPARQL 'SELECT' query returns a table structure,
lets call it :Table, stored in local var 'my:numbers'.
The 'SELECT' query reads from io:stdin which is internally a
db:LineInput for instance,
readable by lines.
Each line is stored in ?line after being casted to xsd:integer.
After 10 lines, reading is stopped.

Some statements can then be automagically added by the interpreter, like :
- my:numbers a :Table

-------------------------------------------------------------------------------
  my:list a  :List.
  ASK { my:numbers :lt my:_knownAge }
   :ontrue :states {
    io:stdout io:print "I already know all artists with age ", my:_knownAge.
    my:file io:print  "known artist".
   };
   :onfalse :states {
    io:stdout io:print "ok, a new data to retrieve is given"..
    my:file io:print "unknown artist with age", my:var.
    my:list :add  ask:subject.
   }.
-------------------------------------------------------------------------------
Creates an simple list.
Creates an 'if' statement with SPARQL 'ASK'. It is possible because interpreter
treats ASK as returning a ':Boolean'.
The interpreter can then allow some operations on booleans, like
':ontrue' and ':onfalse'
for instance.
On each case a list of statements are executed, take the negative case :
prints ordered Literals to io:stdout, the default output stream.
add the 'ASK' query subject retrievable through 'ask:subject' to the
previously created ':List' my:list.
The canvas is then: if the user entered the known artists age '42',
ignore and log, else store
the age for which we will try to retrieve all available artist names.
I know that the '{}' syntax is not Turtle here, but N3, a better
expression has to be found.

-------------------------------------------------------------------------------
  my:db a  db:SparqlEndpoint;
    db:url "http://my.db/endpoint".
-------------------------------------------------------------------------------
Creates a SPARQL endpoint object which can be requested.

-------------------------------------------------------------------------------
  my:artists :constructs CONSTRUCT {
   ?artist  a   mo:MusicalArtist;
      foaf:age ?age;
      foaf:name ?name.
  }
  FROM my:db
  WHERE {
   ?artist  a   mo:MusicalArtist;
      foaf:age ?age;
      foaf:name ?name.
   FILTER( ?age IN my:list. ).
  }.
-------------------------------------------------------------------------------
Creates a ':Graph' stored in my:artists using a 'CONSTRUCT' SPARQL query to the
previously instanciated endpoint my:db.
Retrieve all the artist names and ages for each user-supplied ages.
The interpreter will modify a bit the query, replacing 'my:list' by a
true SPARQL
list syntax.

-------------------------------------------------------------------------------
  my:results :selects SELECT ?name, ?age
  FROM my:artists
  WHERE {
   ?artist  foaf:age ?age;
      foaf:name ?name.
  }.
-------------------------------------------------------------------------------
Creates a ':Table' instance from a SPARQL 'SELECT' query, as previsouly done.
Note that here we are cascading a CONSTRUCT then a SELECT query while a single
SELECT query using 'FROM my:db' is sufficient, it is only to show how to use
a ':Graph' instance.

-------------------------------------------------------------------------------
  my:results :loop :states {
   my:file  io:print "artist ", loop:name, " is aged ", loop:age.
  }.
-------------------------------------------------------------------------------
Operates a loop on the resulting ':Table' my:results.
The local loop vars are retrieved using the header name from the
'loop:' namespace :
loop:name and loop:age which are only valid within the loop...
Print all results to the log file.

You then find a last statement :
-------------------------------------------------------------------------------
:context :call my:main :setarg my:_knownAge :value 42.
-------------------------------------------------------------------------------
Which is used here to demonstrate a way to make function calls, but on
major cases
the idea is more to be able to call root programs using common http as :

http://mysoftwarefactory.com/xturtle/id/first_prog/?_knownAge=42

So, without specific API we could make queries as :
http://mymusicstore.com/xturtle/id/get_artists/?age=42&country=France&xt_format=JSON

A list of all programs can be found with a SPARQL query on an endpoint
on 'rdf:type :Program'.

All of these is really a first attempt to fastly put my ideas on
paper, so a lot of questions
must be resolved if the concept has any interest :
- is there a real need for this kind of approach ?
- xTurtle or really different language with a another semantic syntax ?
- which standard library ? which standard library modules ? How to
extend standard library ?
- can we create bridges from existing languages ?
- is it a turtle modification or the creation of an extension ?
- is turtle the most suitable for this ? N3 (@forAll, @forSome, ..) ?
- is there any other initiatives to make things like this one ?

Thanks a lot for all feed-back you could make.. :)
++

--
mglcel-at-mglcel-dot-fr

Received on Tuesday, 8 March 2011 17:35:37 UTC