- From: Loïc DIAS DA SILVA <mglcel@mglcel.fr>
- Date: Tue, 8 Mar 2011 09:34:31 +0100
- To: public-rdf-comment@w3.org
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