Clojure is an interactive language, in that it provides a REPL -- read-eval-print-loop; what this means is that you can write code interactively, adding and removing functions, to test them out. This turns out to be a surprisingly useful feature of the language. This was one of the original motivations for using Clojure, as adding and removing concepts without the need for a long compile-restart cycle seemed a critical feature. Here we describe use of the REPL and some features of tawny that aid it's use.
How to start the REPL is entirely dependent on the development environment that you are using. For Emacs, the command "M-x nrepl-jack-in" achieves this; for other environments, please read the documentation (it is likely to be near the beginning, since most Clojure developers use the REPL a lot).
Typically, the REPL will have a prompt such as:
user>
This is not shown in this document, as it prevents cutting-and-pasting. The REPL also prints the return value of every form. We show this here preceded with a comment character, again, to enable cutting-and-pasting.
To use the REPL directly, you need to require
or use
the tawny.owl
library. In the default namespace, type:
(use 'tawny.owl)
;;nil
We can now create a new ontology. This can be done with the standard
defontology
form. As it is so useful, there is also an test-ontology
function which can be used to create a "disposable" ontology.
(test-ontology)
;; #<OWLOntologyImpl Ontology(OntologyID(OntologyIRI(<http://iri/>))) [Axioms: 0 Logical Axioms: 0]>
Entities such as classes and properties can be added, using the same commands
as normal. For example, we can create a new class called A
.
(defclass A)
;; #'user/A
The return value here, is Clojure var object created by the defclass
form;
the reasons for this is consistency with Clojure which does this with all
def
form; the reasons for Clojure doing this are a little obscure and not
described here. To see the OWLObject
created, type the variable name again.
A
;; #<OWLClassImpl <http://iri/#A>>
Use of the functional forms will return this value directly.
(owl-class "A")
;; #<OWLClassImpl <http://iri/#A>>
Because of the behaviour of the OWL API, calling this function twice will result in an equivalent object.
(= A (owl-class "A"))
;; true
(= (owl-class "A") (owl-class "A"))
;; true
(= (owl-class "A") (owl-class "B"))
;; false
These functions do have the side effect of adding entities to the ontology. So, for example, after typing the forms above, we find:
(get-current-ontology)
;; #<OWLOntologyImpl Ontology(OntologyID(OntologyIRI(<http://iri/>)))
;; [Axioms: 2 Logical Axioms: 0]>
the current ontology has 2 axioms in total -- we have created (owl-class "B")
.
If we wish to remove the entity again, we can do so. Note that this does not
delete the class or remove it from the namespace, just from the ontology.
(defclass B)
;; #'user/B
B
;; #<OWLClassImpl <http://iri/#B>>
(get-current-ontology)
;; #<OWLOntologyImpl Ontology(OntologyID(OntologyIRI(<http://iri/>)))
;; [Axioms: 2 Logical Axioms: 0]>
(remove-entity B)
;; [#<RemoveAxiom RemoveAxiom(Declaration(Class(<http://iri/#B>))
;; OntologyID(OntologyID(OntologyIRI(<http://iri/>))))>]
B
;; #<OWLClassImpl <http://iri/#B>>
(get-current-ontology)
;; #<OWLOntologyImpl Ontology(OntologyID(OntologyIRI(<http://iri/>)))
;; [Axioms: 1 Logical Axioms: 0]>
Tawny also provides a documentation lookup facility rather like the native Clojure facility, although it operates in a different way. To use this, first the library must be required.
(require 'tawny.repl)
;; nil
We can now check for the documentation. For example:
(tawny.repl/print-doc B)
;; Prints out
;; Class: B
;; IRI: http://iri/#B
;; Labels:
;; Comments:
;; Full Definition:
;; (tawny.owl/defclass http://iri/#B)
;;
;; Returns value!
;; nil
In this case, the documentation string is not that useful, so let's add more
to the definition of B
.
(defoproperty P)
;; #<OWLObjectPropertyImpl <http://iri/#P>>
(defclass B :label "B" :comment "B is a test class" :subclass (owlsome P B))
;; #'user/B
(tawny.repl/print-doc B)
;; Prints out!
;;
;; Class: B
;; IRI: http://iri/#B
;; Labels:
;; "B"@en
;; Comments:
;; "B is a test class"@en
;; Full Definition:
;; (tawny.owl/defclass
;; http://iri/#B
;; :super
;; (owlsome http://iri/#P http://iri/#B)
;; :annotation
;; (owlcomment "B is a test class" "en")
;; (label "B" "en"))
;; Return value!
;; nil
As can be see, comments and labels are printed, as is a "full definition". This is calculated from the object itself, so will work even with definitions that are read from an OWL file.
Tawny can place documentation in the same place as Clojure normally places it; this means that documentation lookup will probably work as with normal functions.
Unfortunately, this is not totally straight-forward; the documentation lookup system of Clojure makes the assumption that Vars are immutable; unfortunately with tawny, the vars point to mutable Java objects. The documentation may change as the ontology is built.
It is possible to update the documentation on the Clojure var to represent the
current state of the ontology using (tawny.repl/update-doc MyClass)
, or
alternatively, to update all the Var in a ns using (tawny.repl/update-ns-doc *ns*)
or (tawny.repl/update-ns-doc (find-ns 'my-namespace))
.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close