Hi Stian,

On Tue, Jul 7, 2015 at 3:38 AM, Stian Soiland-Reyes <[email protected]> wrote:
> Wow, thank you for a great and solid blog post!  This helps a lot for
> my understanding of your view and of
> https://github.com/betehess/free-rdf

Thanks :-)

>From now on, when discussing the two approaches, I will call the
current approach in Commons RDF the "dynamic approach" while I'll call
the `RDF<...>` approach the "static approach". Because that's really
what's happening.

> I think you are proposing a radical approach that takes us out of the
> classical OO world into a more functional (and in many ways more
> beautiful) approach. I am happy to play with it a bit to see where
> this goes. I am particularly interested to have a go with this for my
> dodgy Clojure approach - [1] - and I like your points on immutability.

I would claim that the static approach is still OO :-) It's just that
people often think that OO is (only) about inheritance. You can blame
Java for that.

> For API documentation I am slightly worried about how much harder it
> would be to understand a bunch of methods grouped together, as opposed
> to split per interface. More inter-linking between the methods would
> probably be needed.

One still has to read the entire API. Can you explain your idea re:
"More inter-linking between the methods"?

> I am however also concerned that you are adding a compile-time binding
> to the implementations,

YES!!!! That's why it works.

> which could mean clients no longer would be
> able to dynamically use any RDF implementation.

That is not the case. Keep reading ;-)

> I think your approach
> would only work for clients if they do this passing of the "RDF"
> instance throughout - or if they based it on the 'concrete' interfaces
> as you propose.

Actually, the static approach is _still_ compatible with the dynamic approach.

For example, Apache Any23 could be written/implemented in terms of
`RDF<...>` while exposing one instance of their API using the `Graph`,
`Triple`, etc. defined in Commons RDF. Users would just have to use
it, without worrying about providing the `RDF<...>` instance nor the
abstract types a single time.

It could also do the same for Jena, Sesame, banana-rdf, etc. This
plumbing has to be written only once, either by the Apache Any23
folks, or by any user having an instance of `RDF<...>` in their hands.

> In a way your approach can be fitted into our current approach as an
> optional higher-level abstraction.

I would actually hope the emphasis to be on the static approach so
that library authors would start with it.

It is _always_ possible to plug the interface approach in a system
using the static approach.

> It also means that you could fit
> use say Jena into Commons-RDF this without any object wrappers - just
> a single functional wrapper.  We could even have generic reverse
> wrapper classes that calls the RDF methods per interface.
>
>
> Applications who are not sure which RDF implementation to use, e.g.
> for performance reasons, can with Commons RDF swap implementations
> with no or little changes - with your approach this is not very
> different as it would just mean to pass a different RDF instance in.
>
> But I also saw a big value of Commons RDF being for other libraries
> who just need to do a bit of RDF on the side, so that they can be
> pluggable for alternative RDF frameworks  without forcing an
> implementation choice on their clients. I am not sure if this would
> work with a compiled library - as you say the generics info is
> basically lost on compile in Java.

Again, the interface approach _can_ still be useful. For me, its main
interest is that the APIs in Jena and Sesame will be unified, easier
to learn, and very close to the spec. That's a huge win for everybody.
But I am not sure of the other benefits.

> So I would want to see more on how clients using this - who are not
> implementing RDF in any way, but just wants to make some statements or
> manipulate some graphs - and see if they would still have the benefit
> of Commons RDF without too much buy-in or compile-time options.

As I said, I believe that library authors would probably do the
plumbing themselves most of the time, in the interest of the users.
And if it happens that the library X does not already provide a module
using your favorite RDF implementation, well, then it's just a PR away
;-)

Best,
Alexandre

>
>
>
> [1] https://github.com/stain/commons-rdf-clj/tree/master/src/commons_rdf_clj
>
> On 17 June 2015 at 16:47, Alexandre Bertails <[email protected]> wrote:
>> FYI http://bertails.org/2015/06/17/an-rdf-abstraction-for-the-jvm/
>>
>> Sorry for the long delay.
>>
>> Best,
>> Alexandre
>>
>> On Sun, May 31, 2015 at 4:01 AM, Andy Seaborne <[email protected]> wrote:
>>> On 14/05/15 15:58, Alexandre Bertails wrote:
>>>>
>>>> Thank you Andy, those are the questions that must be answered before
>>>> significant code is being written.
>>>>
>>>> On Thu, May 14, 2015 at 3:37 AM, Andy Seaborne <[email protected]> wrote:
>>>>>
>>>>> Alexandre's proposal would the project in a different direction.
>>>>
>>>>
>>>> Code-wise, this is true, as a lot of existing interfaces would become
>>>> obsolete, so I understand why this is frustrating. But I believe that
>>>> the proposal is better aligned with a larger goal of interop.
>>>
>>>
>>> Could you expand on that because it looks like a different interoperability,
>>> one where code (algorithms) can be easily ported between systems but it's by
>>> recompiling with different choices for RDF<....> whereas factory injection
>>> means the same binary code can work over different systems.
>>>
>>>>> The goals for me have been switching underlying systems (being able to
>>>>> produce portable algorithms that can be applied without recompiling the
>>>>> world (ServiceLoader to bind to implementation) and of interoperation
>>>>> across
>>>>> systems.
>>>>
>>>>
>>>> The pure Scala parts of banana-rdf cannot interoperate using the
>>>> current framework.And in a larger sense, the current Commons RDF does
>>>>
>>>> not accommodate a lot of more general use cases (see the 7 use cases I
>>>> listed in a previous email).
>>>>
>>>> For me, the current approach was driven by the existing Jena and
>>>> Sesame, and that's already progress. The real question is: are there
>>>> other goals we want to address? If the answer is "no" then it's fine
>>>> as well, but we need to know it, and the reason.
>>>>
>>>>> Being able to switch implementation choices by choosing different types
>>>>> is
>>>>> interesting but different. It would be nice to see both existing though
>>>>> combining into one "thing" seems to overload the focus.
>>>>
>>>>
>>>> As I showed in the code, the two can be combined. It is important that
>>>> people here take the time to understand the big picture and how the
>>>> pieces translate.
>>>>
>>>>> Do we want to "host" the generics approach as well (whether used for the
>>>>> system abstraction work or to go along side)?
>>>>
>>>>
>>>> Very good question. I believe library authors will want their work to
>>>> be usable to more people, not just Jena and Sesame. So if  the
>>>> "generics approach" doesn't happen in Commons RDF, then people with
>>>> interest in better interop will have an incentive to maintain the code
>>>> outside of the project. Especially if they know that there is an easy
>>>> way to communicate with the interfaces from Commons RDF, with no
>>>> runtime cost.
>>>>
>>>>> The other difference is a theory-practice one. The current work is not
>>>>> reworking the general style of Jena, Sesame,
>>>>
>>>>
>>>> The "general style of Jena, Sesame" was not driven by interop. So
>>>> people had different problems to solve and OOP was perfectly fine in
>>>> that case.
>>>>
>>>>> common progamming ways of doing things.
>>>>
>>>>
>>>> I simply don't know what "common programming". In some cases, I have
>>>> heard people using that term to dismiss other forms of programming.
>>>>
>>>> What I know is that the approach in my proposal is not new at all, and
>>>> has existed in Java-land for a long time. Just look at
>>>> java.util.Comparator vs java.util.Comparable, that is the very same
>>>> discussion, just with a few more types.
>>>>
>>>> First we need to agree (or not) on the goals, then we find a technical
>>>> solution. And again, "not interested" is a perfectly fine answer.
>>>>
>>>>> I'd like to see the generics approach validated by external usage,
>>>>> not for its technical design, but addressing whether it creates
>>>>> sufficient
>>>>> demand and sufficient acceptance.
>>>>
>>>>
>>>> As for the design itself, you can consider it's been incubated in
>>>> banana-rdf for four years.
>>>>
>>>> Alexandre
>>>>
>>>> [1] http://en.wikipedia.org/wiki/Type_class
>>>>
>>>>>
>>>>>          Andy
>>>>>
>>>>>
>>>>> On 13/05/15 07:32, Alexandre Bertails wrote:
>>>>>>
>>>>>>
>>>>>> Sergio,
>>>>>>
>>>>>> The approach is different. A "patch" against the current codebase
>>>>>> would remove most of the interfaces.
>>>>>>
>>>>>> I suggest that you try to understand what's going on in the code,
>>>>>> after you read the other messages in that thread.
>>>>>>
>>>>>> Then if there is interest, I can work on a real patch.
>>>>>>
>>>>>> Alexandre
>>>>>>
>>>>>> On Tue, May 12, 2015 at 11:25 PM, Sergio Fernández <[email protected]>
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>> I'd say if you'd be much more valuable to see a patch about your
>>>>>>> proposal
>>>>>>> that a quick hack from scratch.
>>>>>>> You can fork our github mirror:
>>>>>>> https://github.com/apache/incubator-commonsrdf
>>>>>>>
>>>>>>> On Wed, May 13, 2015 at 8:01 AM, Alexandre Bertails
>>>>>>> <[email protected]>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> On Tue, May 12, 2015 at 10:21 PM, Sergio Fernández <[email protected]>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Alexandre,
>>>>>>>>>
>>>>>>>>> git clone
>>>>>>>>>
>>>>>>>>> https://[email protected]/repos/asf/incubator-commonsrdf.git
>>>>>>>>> commonsrdf
>>>>>>>>>
>>>>>>>>> The incubator prefix in the name is to keep clear we're still not
>>>>>>>>> fully
>>>>>>>>> endorsed by the ASF. I know it's a bit inconvenient, specially in
>>>>>>>>> later
>>>>>>>>> phases when we'd get rid of that, but is part of the incubator
>>>>>>>>> process.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks!
>>>>>>>>
>>>>>>>> I have hacked something quick-and-dirty and made it available at [1].
>>>>>>>>
>>>>>>>> Quick overview of the sub-packages:
>>>>>>>> * `api`: just the RDF interface, and the interfaces from commons-rdf
>>>>>>>> are moved under `concrete`
>>>>>>>> * `concrete`: shows how to implement RDF with the interfaces approach
>>>>>>>> * `simple`: a complete example adapted from commons-rdf
>>>>>>>> * `classless`: a (almost) complete example which does not rely on
>>>>>>>> shared interfaces
>>>>>>>> * `turtle`: a example of how to rely on the RDF interface
>>>>>>>>
>>>>>>>> Feel free to ask questions.
>>>>>>>>
>>>>>>>> Alexandre
>>>>>>>>
>>>>>>>> [1] https://github.com/betehess/free-rdf
>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Tue, May 12, 2015 at 6:45 PM, Alexandre Bertails <
>>>>>>>>
>>>>>>>>
>>>>>>>> [email protected]>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> Stian,
>>>>>>>>>>
>>>>>>>>>> It sounds stupid but I do not understand where the code actually
>>>>>>>>>> lives.
>>>>>>>>>>
>>>>>>>>>> I have tried
>>>>>>>>>>
>>>>>>>>>> ```
>>>>>>>>>> git clone https://git-wip-us.apache.org/repos/asf/commons-rdf.git
>>>>>>>>>> ```
>>>>>>>>>>
>>>>>>>>>> and
>>>>>>>>>>
>>>>>>>>>> ```
>>>>>>>>>> git clone git://git.apache.org/commons-rdf.git
>>>>>>>>>> ```
>>>>>>>>>>
>>>>>>>>>> but both tell me that I "appear to have cloned an empty repository."
>>>>>>>>>> The github repo is empty as well.
>>>>>>>>>>
>>>>>>>>>> Can somebody please give me the right URI? Sorry if I miss that in
>>>>>>>>>> the
>>>>>>>>>> documentation, but I did look there and couldn't find the answer :-/
>>>>>>>>>>
>>>>>>>>>> Alexandre
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Tue, May 12, 2015 at 8:41 AM, Alexandre Bertails
>>>>>>>>>> <[email protected]> wrote:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Hi Stian,
>>>>>>>>>>>
>>>>>>>>>>> On Tue, May 12, 2015 at 7:35 AM, Stian Soiland-Reyes <
>>>>>>>>
>>>>>>>>
>>>>>>>> [email protected]>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 12 May 2015 at 06:20, Alexandre Bertails
>>>>>>>>>>>> <[email protected]>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> I actually didn't understand that we were discussing a
>>>>>>>>>>>>> `createBlankNode(UUID)`. I think we just need to be able to
>>>>>>>>>>>>> create
>>>>>>>>>>>>> a
>>>>>>>>>>>>> fresh blank node.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> That is what createBlankNode() does.
>>>>>>>>>>>>
>>>>>>>>>>>> Is your proposal to simply remove createBlankNode(String)?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> As it is today, yes. Because its contract implies some kind of
>>>>>>>>>>> shared
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> state.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> But we have identified a use-case where the blank node can remember
>>>>>>>>>>> in
>>>>>>>>>>> which context it was generated e.g. the blank node label at parsing
>>>>>>>>>>> time.
>>>>>>>>>>>
>>>>>>>>>>>>> Requiring the caller to provide an explicit UUID
>>>>>>>>>>>>> means that the freshness is happening *outside* of the factory,
>>>>>>>>>>>>> so
>>>>>>>>>>>>> I
>>>>>>>>>>>>> don't see the point.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Well, you wanted to pass in the uniqueness..? You can pass it as a
>>>>>>>>>>>> String (as of today), or, loosely suggested, by restricting this
>>>>>>>>>>>> to
>>>>>>>>>>>> a
>>>>>>>>>>>> UUID (which would require clients to think about this very common
>>>>>>>>>>>> mapping/hashing).
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> No, the uniqueness must happen in `createBlankNode()`. That's how
>>>>>>>>>>> you
>>>>>>>>>>> can enforce the invariant.
>>>>>>>>>>>
>>>>>>>>>>>>> Also, it's forcing the strategy (UUID), which
>>>>>>>>>>>>> might not be the best one for everybody, e.g. UUID is known to be
>>>>>>>>>>>>> slow, at least for some notion of slow, and that could become a
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> There are several variations of UUID, you are free to use a
>>>>>>>>>>>> timestamp one that is rather fast to make, SHA-1 is not known to
>>>>>>>>>>>> be
>>>>>>>>
>>>>>>>>
>>>>>>>> slow
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> either, so version 5 hashes are also fast.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> commons-rdf should leave that choice open.
>>>>>>>>>>>
>>>>>>>>>>>> But we agreed that UUID only might be a bit strict for some
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> implementations,
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> which meant that uniqueReference() can return any unique string..
>>>>>>>>>>>> so
>>>>>>>>
>>>>>>>>
>>>>>>>> if
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> it
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> considered
>>>>>>>>>>>>
>>>>>>>>>>>>     app=97975c0b-62c1-42c9-b2a9-e87948e4a46e ip=84.92.48.26
>>>>>>>>>>>> uid=1000
>>>>>>>>>>>> pid=292 name=fred
>>>>>>>>>>>>
>>>>>>>>>>>> to be a unique string (with hard-coded
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> 97975c0b-62c1-42c9-b2a9-e87948e4a46e
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> in case someone else comes up with a similar scheme),
>>>>>>>>>>>> and didn't mind leaking all that vulnerability data, then that
>>>>>>>>>>>> would
>>>>>>>>
>>>>>>>>
>>>>>>>> be
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> a
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> compliant uniqueReference().
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> I am not arguing for stateless vs stateful. I am just pointing at
>>>>>>>>
>>>>>>>>
>>>>>>>> some
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> design issues which do not allow it. Currently, there is just no
>>>>>>>>>>>>> way
>>>>>>>>>>>>> for an immutable implementation to be used with such a factory.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I am not sure what is the extent of "immutable" here. I'll assume
>>>>>>>>>>>> it
>>>>>>>>>>>> just means that all fields are final, not
>>>>>>>>>>>> that the object is not allowed to have any field at all.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Being final just means that the reference won't be updated, but its
>>>>>>>>>>> state can still be updated. So to be immutable, you also need the
>>>>>>>>>>> final references to be immutable themselves.
>>>>>>>>>>>
>>>>>>>>>>>> You are free to
>>>>>>>>>>>> create RDFTermFactory as you please, so you can simply do it like
>>>>>>>>
>>>>>>>>
>>>>>>>> this:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> public class ImmutableRDFTermFactory implements RDFTermFactory {
>>>>>>>>>>>>       private final UUID salt;
>>>>>>>>>>>>       public ImmutableRDFTermFactory(UUID salt) {
>>>>>>>>>>>>           this.salt = salt;
>>>>>>>>>>>>       }
>>>>>>>>>>>>       public BlankNode createBlankNode() {
>>>>>>>>>>>>         return new BlankNodeImpl(salt);
>>>>>>>>>>>>       }
>>>>>>>>>>>>       public BlankNode createBlankNode(String name) {
>>>>>>>>>>>>         return new BlankNodeImpl(salt, name);
>>>>>>>>>>>>       }
>>>>>>>>>>>>       / ..
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>> public class BlankNodeImpl implements BlankNode {
>>>>>>>>>>>>
>>>>>>>>>>>>     private static void unique(UUID salt) {
>>>>>>>>>>>>        Instant now = Clock.systemUTC().instant();
>>>>>>>>>>>>        return salt.toString()  + System.identityHashCode(this) +
>>>>>>>>>>>> now.getEpochSecond() + now.getNano() +
>>>>>>>>
>>>>>>>>
>>>>>>>> Thread.currentThread().getId();
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>     }
>>>>>>>>>>>>
>>>>>>>>>>>>     private final String uniqueReference;
>>>>>>>>>>>>     public BlankNodeImpl(UUID salt, String name) {
>>>>>>>>>>>>       uniqueReference = salt.toString() + name;
>>>>>>>>>>>>     }
>>>>>>>>>>>>     public BlankNodeImpl(UUID salt) {
>>>>>>>>>>>>       uniqueReference = salt.toString()  +
>>>>>>>>
>>>>>>>>
>>>>>>>> System.identityHashCode(this)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> + new Date().;
>>>>>>>>>>>>     }
>>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> This is not immutable because of the shared state.
>>>>>>>>>>>
>>>>>>>>>>>> Here there is no hidden mutability in AtomicLong or within
>>>>>>>>>>>> java.util.UUID's SecureRandom implementation's internal state. I
>>>>>>>>
>>>>>>>>
>>>>>>>> guess
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> you would not be happy with those either?
>>>>>>>>>>>>
>>>>>>>>>>>> The clock is obviously mutable - but as a device rather than a
>>>>>>>>>>>> memory
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> state.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> There is no "but" in the immutable world :-)
>>>>>>>>>>>
>>>>>>>>>>>>> Having `add` returning a `Graph` does not mean that `Graph` is
>>>>>>>>>>>>> immutable. It just means that it *enables* `Graph` to be
>>>>>>>>>>>>> immutable.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> There is nothing stopping an immutable Graph from having an
>>>>>>>>
>>>>>>>>
>>>>>>>> additional
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> method that does this.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Now I am the one asking for some code, because I don't see how
>>>>>>>>>>> that'd
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> work :-p
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> As I said in a previous, you can wrap an immutable Graph in a new
>>>>>>>>>>> object with a mutable reference to that graph, but, well, please
>>>>>>>>>>> let's
>>>>>>>>>>> avoid having to do that...
>>>>>>>>>>>
>>>>>>>>>>>> For some methods, like builders, returning the mutated state is
>>>>>>>>>>>> good
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> practice.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> When using persistent datastructures, a builder is not an option.
>>>>>>>>>>>
>>>>>>>>>>> There are areas where you do not want to go back to the mutable
>>>>>>>>>>> version. It happens everywhere in banana-rdf e.g. the RDF DSL, the
>>>>>>>>>>> RDF/class mapper, etc. Just because we need to compose graphs
>>>>>>>>>>> without
>>>>>>>>>>> risking to modify an existing one.
>>>>>>>>>>>
>>>>>>>>>>>> It has been suggested earlier to return bool on add() to be
>>>>>>>>
>>>>>>>>
>>>>>>>> compatible
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> with Collection, but we were not all too happy with that as it
>>>>>>>>>>>> might
>>>>>>>>>>>> be difficult/expensive to know if the graph was actually mutated
>>>>>>>>>>>> or
>>>>>>>>>>>> not (e.g. you insert the same triple twice, but the store doesn't
>>>>>>>>>>>> bother checking if the triple existed).
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Returning `bool` has very little value from my perspective.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> See
>>>>>>>>>>>> https://issues.apache.org/jira/browse/COMMONSRDF-17
>>>>>>>>>>>> https://github.com/commons-rdf/commons-rdf/issues/27
>>>>>>>>>>>> https://github.com/commons-rdf/commons-rdf/issues/46
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> So your suggestion is for the mutability methods to return the
>>>>>>>>
>>>>>>>>
>>>>>>>> mutated
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> object (which may or may not be the original instance). I think
>>>>>>>>>>>> this
>>>>>>>>>>>> could be an interesting take for discussions - could you raise
>>>>>>>>>>>> this
>>>>>>>>
>>>>>>>>
>>>>>>>> as
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> a separate Jira issue?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Yes, that'd be the way to go.
>>>>>>>>>>>
>>>>>>>>>>> But I would prefer to see how much interest in the general approach
>>>>>>>>>>> there is before opening too many issues.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Well, Scala is just a language. Immutability and referential
>>>>>>>>>>>>> transparency, are just principles, but they are becoming more and
>>>>>>>>
>>>>>>>>
>>>>>>>> more
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> important in many areas (Spark, concurrency, etc.).
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Agreed, also for distributed areas like Hadoop.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> There are *many* areas where accommodating immutable graphs has
>>>>>>>>>>> become
>>>>>>>>>>> important.
>>>>>>>>>>>
>>>>>>>>>>>>> There is no shortcut at all. The RDF model only resolves around
>>>>>>>>>>>>> some
>>>>>>>>>>>>> types (Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI, BlankNode,
>>>>>>>>>>>>> Literal) which can be left abstract, as opposed to being concrete
>>>>>>>>
>>>>>>>>
>>>>>>>> when
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> using Java's interfaces. (it's "concrete" in the sense it's using
>>>>>>>>>>>>> nominal subtyping)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Well, I still don't see how a java.util.String will work with Java
>>>>>>>>>>>> code that expects to be able to call .getIRIString(). Would
>>>>>>>>>>>> Scala generate proxies on the fly?  Or would it need to call
>>>>>>>>>>>> .getIRIString() "elsewhere"?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> It's like monkey patching, just in a controlled and type safe way:
>>>>>>>>>>>
>>>>>>>>>>> ```
>>>>>>>>>>> val rdf: RDF = ???
>>>>>>>>>>>
>>>>>>>>>>> implicit class IRIWrapper(val iri: IRI) extends AnyVal {
>>>>>>>>>>>     def getIRIString(): String = rdf.getIRIString(iri)
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> val iri: IRI = rdf.createIRI("http://example.com";)
>>>>>>>>>>> assert(rdf.getIRIString(iri) == iri.getIRIString())
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>> Scala would find that there is an implicit conversion from IRI to
>>>>>>>>>>> something with a getIRIString method, and would do the `new
>>>>>>>>>>> IRIWrapper`. But because this is also a value class (`AnyVal`) then
>>>>>>>>>>> no
>>>>>>>>>>> object would actually be allocated. It's basically free.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> If you look at what I did, you have a *direct* translation of the
>>>>>>>>>>>>> existing interfaces+methods+factory into simple functions.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Yes, but done in Scala. Can I see a suggestion to the changes of
>>>>>>>>>>>> the
>>>>>>>>>>>> current CommonsRDF Java interfaces - in Java?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> No the gist is in Java and uses the same function names.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> * the Java interfaces becomes abstract types
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Java interfaces are abstract types.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Java interfaces provide some abstraction (subtype polymorphism).
>>>>>>>>>>> Types
>>>>>>>>>>> are compile-time information. At runtime, you see a reified version
>>>>>>>>>>> of
>>>>>>>>>>> the type, as an interface or as a class (and module type erasure).
>>>>>>>>>>> That is why Java interfaces are not really abstract types.
>>>>>>>>>>>
>>>>>>>>>>>> Do you mean generics?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Yes.
>>>>>>>>>>>
>>>>>>>>>>>>    Generics of which class/interface?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Of the RDF interface in the gist [1].
>>>>>>>>>>>
>>>>>>>>>>> [1]
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> https://gist.github.com/betehess/8983dbff2c3e89f9dadb#file-rdf-java-L10
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>> Not all Commons RDF clients are expected to interface via
>>>>>>>>>>>> RDFTermFactory. In fact many use-cases don't need it at all.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> * the methods on those interfaces become functions on the
>>>>>>>>>>>>> abstract
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> types
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> * the methods on the interfaces in the factory becomes simple
>>>>>>>>>>>>> functions on the abstract types
>>>>>>>>>>>>> * operating on a node happens with a visitor (as in visitor
>>>>>>>>>>>>> pattern)
>>>>>>>>>>>>> implemented as the `visit` function, taking 3 functions for the 3
>>>>>>>>>>>>> possible cases (I believe the current API asks for checking the
>>>>>>>>
>>>>>>>>
>>>>>>>> class
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> at runtime...)
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> This is too much at an abstract (!) level for me to visualize as
>>>>>>>>
>>>>>>>>
>>>>>>>> we're
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> clashing programming languages here.. could you detail how this
>>>>>>>>>>>> would
>>>>>>>>>>>> look in a set of *.java files? Feel free to raise it as a pull
>>>>>>>>
>>>>>>>>
>>>>>>>> request
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> or similar, even if it's very draft-like. :)
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I can transform my gist into a real project. I will need a couple
>>>>>>>>>>> of
>>>>>>>>>>> days to find the time.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Now, let's say I am implementing a Turtle parser. The only thing
>>>>>>>>>>>>> I
>>>>>>>>>>>>> care about is how I can [use case 1] create/inject elements into
>>>>>>>>
>>>>>>>>
>>>>>>>> some
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> existing RDF model. If I am writing a Turtle serializer, I only
>>>>>>>>>>>>> care
>>>>>>>>>>>>> about how to [use case 2] traverse that type hierarchy. In none
>>>>>>>>>>>>> of
>>>>>>>>>>>>> those cases did I care about having the types defined in the
>>>>>>>>>>>>> class/interface hierarchy and I want anybody to use their own RDF
>>>>>>>>>>>>> model.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Yes. And with the current take of Commons RDF, the Turtle parser
>>>>>>>>>>>> is
>>>>>>>>
>>>>>>>>
>>>>>>>> free
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> to return its own instances of RDFTerm interfaces, which any
>>>>>>>>>>>> Commons
>>>>>>>>
>>>>>>>>
>>>>>>>> RDF
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> consuming client will be able to use as-is, e.g. pass to their own
>>>>>>>>>>>> Graph implementation.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> And here is what people will end up doing:
>>>>>>>>>>>
>>>>>>>>>>> ```
>>>>>>>>>>> Graph graph = JenaTurtleParser.parse(input);
>>>>>>>>>>> com.hp.hpl.jena.graph.Graph jenaGraph =
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> (com.hp.hpl.jena.graph.Graph)graph;
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> ```
>>>>>>>>>>>
>>>>>>>>>>> Many will not want to see the common interface but the actual
>>>>>>>>>>> subtype.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> class TurtleParser<Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI,
>>>>>>>>>>>>> BlankNode, Literal> {
>>>>>>>>>>>>>     RDF<Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI, BlankNode,
>>>>>>>>
>>>>>>>>
>>>>>>>> Literal>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> rdf
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>     Graph parse(String input) { /* can call
>>>>>>>>>>>>> rdf.createLiteral("foo"),
>>>>>>>>
>>>>>>>>
>>>>>>>> or
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> anything in rdf.* */ }
>>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I think the <brackets> speak for themselves here :-(
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> "Small" remark: I still don't think that
>>>>>>>>>>>>> `createBlankNode(String)`
>>>>>>>>>>>>> belongs to the RDF model. I would really like to see a use case
>>>>>>>>>>>>> that
>>>>>>>>>>>>> shows why it has to be present.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> This is a valid point of view which I think you should raise
>>>>>>>>>>>> as a new Jira issue. We did argue that it is not part of the
>>>>>>>>>>>> RDF model, but it is still a practically very useful feature,
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> "useful feature" --> this is where I would like to see a motivating
>>>>>>>>>>> use case. Then we can discus how useful a feature it is, or how
>>>>>>>>>>> much
>>>>>>>>>>> of a problem it can be.
>>>>>>>>>>>
>>>>>>>>>>>> however it has generated many contention points in the past
>>>>>>>>>>>> as it touches on state and uniqueness.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> See also this discussion about the need (or not) for
>>>>>>>>>>>> exposing .uniqueReference()
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I am all in favor or `uniqueReference`. That is how the invariants
>>>>>>>>>>> on
>>>>>>>>>>> the blank node can be achieved.
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> https://issues.apache.org/jira/browse/COMMONSRDF-13
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Finally, I will admit that writing all those types parameters can
>>>>>>>>
>>>>>>>>
>>>>>>>> be a
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> bit cumbersome, even if it happens only in a very few places (as
>>>>>>>>>>>>> a
>>>>>>>>>>>>> user: only once when you build what you need e.g. a Turtle
>>>>>>>>>>>>> parser).
>>>>>>>>>>>>> But please let's not sacrifice correctness and functionality to
>>>>>>>>>>>>> (a
>>>>>>>>>>>>> little) convenience...
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Well, if those would be exposed to any client of the Commons RDF
>>>>>>>>>>>> API
>>>>>>>>
>>>>>>>>
>>>>>>>> I
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> fear we would see very little uptake..
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> How so?
>>>>>>>>>>>
>>>>>>>>>>>> If they are hidden inside some upper/inner interface that is not
>>>>>>>>>>>> exposed otherwise, it is not so bad.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Yes, you can always do that.
>>>>>>>>>>>
>>>>>>>>>>> Alexandre
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>>> Stian Soiland-Reyes
>>>>>>>>>>>> Apache Taverna (incubating), Apache Commons RDF (incubating)
>>>>>>>>>>>> http://orcid.org/0000-0001-9842-9718
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Sergio Fernández
>>>>>>>>> Partner Technology Manager
>>>>>>>>> Redlink GmbH
>>>>>>>>> m: +43 6602747925
>>>>>>>>> e: [email protected]
>>>>>>>>> w: http://redlink.co
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Sergio Fernández
>>>>>>> Partner Technology Manager
>>>>>>> Redlink GmbH
>>>>>>> m: +43 6602747925
>>>>>>> e: [email protected]
>>>>>>> w: http://redlink.co
>>>>>
>>>>>
>>>>>
>>>
>
>
>
> --
> Stian Soiland-Reyes
> Apache Taverna (incubating), Apache Commons RDF (incubating)
> http://orcid.org/0000-0001-9842-9718

Reply via email to