- 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