Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easy way to convert RDF Lists to Arrays #15

Closed
joepio opened this issue Sep 18, 2019 · 1 comment
Closed

Easy way to convert RDF Lists to Arrays #15

joepio opened this issue Sep 18, 2019 · 1 comment
Labels

Comments

@joepio
Copy link
Contributor

joepio commented Sep 18, 2019

A developer playing with RDF will, sooner or later, realize that RDF does not support Arrays. RDF Lists have their merits, but they are a struggle to deal with as a front-ender.

If I want to render an RDF list, I'd need to register a view like this one:

import React from "react";
import { register, Property, useLinkRenderContext } from "link-redux";

import { NS } from "../../LRS";
import allTopologies from "../Topologies/allTopologies";

const RDFList = () => {
  const { subject } = useLinkRenderContext()

  // Without this, it renders the nil - which often looks weird
  // Also requires this in the ontology: 
  //new Statement(NS.rdf("nil"), NS.rdf("type"), NS.rdf("List")),

  if (subject.value === NS.rdf("nil").value) {
    return null;
  }

  return (
    <React.Fragment>
      <Property label={NS.rdf("first")}/>
      <Property label={NS.rdf("rest")}/>
    </React.Fragment>
  );
};

RDFList.type = NS.rdf("List");
RDFList.topology = allTopologies;

export default register(RDFList);

Which has a couple of problems:

  • It creates a huge nested set of components, instead of a linear list
  • I can't manipulate the array in a way that empowers me as a front-ender. No map, filter, push.

I feel like link-lib, link-redux or maybe rdflib should provide a sensible way to help with RDF Lists.

Perhaps the mapDataToProps function could default to return RDF lists as arrays? Perhaps the Collection model of rdflib.js can be used?

@rescribet
Copy link
Owner

Realize that RDF does not support Arrays

Expressing a list of objects is present in the core RDF model via rdf:Seq (basic ordered list) or rdf:List (linked list)

If I want to render an RDF list, I'd need to register a view like this one:

That is the canonical and recommended way, it will protect the application against assuming too much (e.g. the given 'array' isn't a rdf:List but rather a rdf:Seq or as:PaginatedCollection) and allows easy expansion of future behaviour by simply registering views for the new topology or data structure.

It creates a huge nested set of components, instead of a linear list

That is the effect of using linked lists, it's possible to remap the underlying data structure, but you'll have to be certain the list isn't too big to fit in memory (Despite the turtle serialisation implying they're always local, RDF:Lists may be distributed across the web).

I can't manipulate the array in a way that empowers me as a front-ender. No map, filter, push

It's a data model generally expressed via some serialization format, so it follows that these things aren't present when working with the data on the e.g. rdf:List level. To quote the JSON spec; An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence. So they are called array in the spec, but aren't arrays in the sense of JS arrays, since it's plain text (not in-memory objects).

Note that push modifies in-place, so it will break your React code, which shows that the ease of use comes at a cost (and a source of obscure bugs).

Perhaps the Collection model of rdflib.js

That isn't RDF, so that's not an option since it would complicate the core data structures (and thus all downstream code).

Perhaps the mapDataToProps function could default to return RDF lists as arrays

There aren't really good defaults for all use-cases (i.e. sync, fetching, invalidation/updating, supporting other data structures, return type, limits/pagination, filtering/sorting) and link-redux is too low-level to make those assumptions. The next version should be able to support this since downstream will be able to write their own mapping functions (though mapping functions will probably reduce code generality and composability, so a costly choice in terms of scalability).

I feel like link-lib, link-redux or maybe rdflib should provide a sensible way to help with RDF Lists

As you mentioned, rdflib already has the collection term, but they make assumptions and come at a cost, the aforementioned push (and slice) for example break in a React context (We had those bug in our front-end and ended up removing the Collection elements). I'm curious to see how it handles edge-cases like distributed and circular lists (What if you wan't to do something else in one instance? Can you disable the parsing of Collections for one class?). AFAICT this is out-of-scope for these low-level libraries since there are just too many options, which surface almost directly when going beyond a TODO app (E.g. using as:PaginatedCollection).

In the meantime, it's trivial to write these functions with the behaviour fit for the current use-case (and an eye on the data source). Mash will also include some reusable helpers for creating delta's for manipulating rdf:Seq objects but those aren't done yet. Mash development will probably produce some utility libraries in the future which hold functions for this, once optimal subsets of behaviour have been found.

P.s. rdf:nil rdf:type rdf:List should already be present in the store since it is a RDF axiom, so that is a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants