Re: 101 on simple and flexible graph query/update?

2014-07-11 Thread Bertrand Dechoux
@Francois Rey : I totally forgot that Datomic could be used on regular data 
structures. Thanks a lot, it might indeed be something to investigate.

@Frank Castellucci : Indeed, I guess someone working with ontologies would 
have the same concerns. Thanks for all the pointers.

Le vendredi 11 juillet 2014 03:48:51 UTC+2, Frank Castellucci a écrit :

 Bertrand

 I've been doing a lot of Ontology (OWL) with directed graphs (with cycles) 
 and DAGS. One application we went with the nested map structure however now 
 that I've been working on a normalized BPMN/XPDL utility ( 
 https://github.com/FrankC01/tributary 
 https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FFrankC01%2Ftributarysa=Dsntz=1usg=AFQjCNGzsWatrlDLLVU4uXDM-UEbR_wDjA
  
 ) I'm becoming enamored with the in XML format produced by xml-parse and 
 then zipping it up. Coupled with clojures 'functional' nature, zippers 
 become your friend really quickly and provide a most generic way of dealing 
 with any graph with any number of layers.

 The next step will be a normalized DSL on top of the zippers and using 
 things like hickory-parse/data.zip selector concepts.

 For the Ontology work we use datomic as the persist mechanism.



 On Thursday, July 10, 2014 4:26:33 AM UTC-4, Bertrand Dechoux wrote:

 Hi,

 I have various general questions about how one can perform simple and 
 flexible graph query/update.

 If we start by a structure being nested maps then I know about 
 get-in/update-in/assoc-in. The common point about these functions is that 
 they all take a path to where the data is in the superstructure and that 
 this path is only a sequence of keys, which may or not be symbols.

 1) What happens when one layer of this superstructure is not a map but a 
 sequence? For the sake of the argument, we can keep the discussion simple 
 by only arguing about the vector case.

 Typically instead of
 { :key1 { :key2 val }}

 we now have
 { :key1 [{ :key2 val }]}

 Of course, one can perform get/update/assoc using map/reduce. However, it 
 means that the code using this superstructure is taking a hit on 
 complexity/maintenance each time a non-map layer must be crossed. Of 
 course, the simplicity/beauty of the current implementation is that a path 
 can point to at most one target substructure/value. Is there a way to do 
 something similar with a more general definition of a path? One would 
 assume that it is something that might be handled by xml/html modification 
 libraries (think xpath or css selector) but this problem is more general 
 and not domain specific. Is there a clean library that handle that case 
 without being tied to html/xml?

 2) How to deal with more general superstructure like a graph?

 One could build an immutable graph but I don't believe it is something 
 that can be done by nesting immutable maps and vectors. One solution to 
 deal with 'entity'--'entity' relationships is for one of the member to own 
 only an identifier to get the other member from another reference structure.

 (from the basic OM tutorial:)

 {:people
  [{:type :student :first Ben :last Bitdiddle}
   {:type :professor :first Gerald :last Sussman :classes [:6001 
 :6946]}]
  :classes
  {:6001 The Structure and Interpretation of Computer Programs
   :6946 The Structure and Interpretation of Classical Mechanics
   :1806 Linear Algebra}}


 It is, of course, again, manually possible to get/update/assoc using 
 map/reduce.  But then, again, this is the same problematic as with the 
 first question : each time a relation needs to be crossed, the code using 
 this superstructure is taking a hit on complexity/maintenance. How do you 
 usually deal with this problematic?

 For both question 1) and 2), a more appropriate data structure might be 
 the answer like a graph/semantic-like store (Datomic or something else). 
 The questions are about intermediary solutions which would be less heavier.

 3) How does Demeter lives with graph traversal?

 This law is often heard in the OOP world but it is a bit more general 
 than that. When a long path on a superstructure is specified then if one 
 intermediary layer is introduced later, all hardcoded paths will be broken 
 ie in multiple locations in the code base. One would like to store local 
 structure knowledge in a single place. How do you usually deal with this 
 problematic?

 I have yet to take a serious look at lenses and their composition, they 
 are probably an element of answer, but they are more often seen in more 
 statically typed langage.

 Thanks for any feedback.

 Bertrand



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at

101 on simple and flexible graph query/update?

2014-07-10 Thread Bertrand Dechoux
Hi,

I have various general questions about how one can perform simple and 
flexible graph query/update.

If we start by a structure being nested maps then I know about 
get-in/update-in/assoc-in. The common point about these functions is that 
they all take a path to where the data is in the superstructure and that 
this path is only a sequence of keys, which may or not be symbols.

1) What happens when one layer of this superstructure is not a map but a 
sequence? For the sake of the argument, we can keep the discussion simple 
by only arguing about the vector case.

Typically instead of
{ :key1 { :key2 val }}

we now have
{ :key1 [{ :key2 val }]}

Of course, one can perform get/update/assoc using map/reduce. However, it 
means that the code using this superstructure is taking a hit on 
complexity/maintenance each time a non-map layer must be crossed. Of 
course, the simplicity/beauty of the current implementation is that a path 
can point to at most one target substructure/value. Is there a way to do 
something similar with a more general definition of a path? One would 
assume that it is something that might be handled by xml/html modification 
libraries (think xpath or css selector) but this problem is more general 
and not domain specific. Is there a clean library that handle that case 
without being tied to html/xml?

2) How to deal with more general superstructure like a graph?

One could build an immutable graph but I don't believe it is something that 
can be done by nesting immutable maps and vectors. One solution to deal 
with 'entity'--'entity' relationships is for one of the member to own only 
an identifier to get the other member from another reference structure.

(from the basic OM tutorial:)

{:people
 [{:type :student :first Ben :last Bitdiddle}
  {:type :professor :first Gerald :last Sussman :classes [:6001 :6946]}]
 :classes
 {:6001 The Structure and Interpretation of Computer Programs
  :6946 The Structure and Interpretation of Classical Mechanics
  :1806 Linear Algebra}}


It is, of course, again, manually possible to get/update/assoc using 
map/reduce.  But then, again, this is the same problematic as with the 
first question : each time a relation needs to be crossed, the code using 
this superstructure is taking a hit on complexity/maintenance. How do you 
usually deal with this problematic?

For both question 1) and 2), a more appropriate data structure might be the 
answer like a graph/semantic-like store (Datomic or something else). The 
questions are about intermediary solutions which would be less heavier.

3) How does Demeter lives with graph traversal?

This law is often heard in the OOP world but it is a bit more general than 
that. When a long path on a superstructure is specified then if one 
intermediary layer is introduced later, all hardcoded paths will be broken 
ie in multiple locations in the code base. One would like to store local 
structure knowledge in a single place. How do you usually deal with this 
problematic?

I have yet to take a serious look at lenses and their composition, they are 
probably an element of answer, but they are more often seen in more 
statically typed langage.

Thanks for any feedback.

Bertrand

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread Thomas Heller
I usually just give every ENTITY in my system a primary id and structure 
everything in a nested map.

{:people {1 {:id 1 :type :student :name Ben :taking-classes #{1 2}}
  2 ...}
 :classes {1 {:id 1 :name Clojure 101}
   2 ...}}

This basically looks like a database table. You can also go with something 
a little more flat.

{1 {:type :student, :name Ben :taking-classes #{3}}
 3 {:type :class, :name Clojure 101}}

Usually needs some form of indexing otherwise you are taking some 
performance hits if you have alot of entities in your system. You dont want 
to (- (vals @data) (filter #(= :class (:type %))) every time you want to 
list all :classes.

Nothing fancy but it is simple. 


On Thursday, July 10, 2014 10:26:33 AM UTC+2, Bertrand Dechoux wrote:

 Hi,

 I have various general questions about how one can perform simple and 
 flexible graph query/update.

 If we start by a structure being nested maps then I know about 
 get-in/update-in/assoc-in. The common point about these functions is that 
 they all take a path to where the data is in the superstructure and that 
 this path is only a sequence of keys, which may or not be symbols.

 1) What happens when one layer of this superstructure is not a map but a 
 sequence? For the sake of the argument, we can keep the discussion simple 
 by only arguing about the vector case.

 Typically instead of
 { :key1 { :key2 val }}

 we now have
 { :key1 [{ :key2 val }]}

 Of course, one can perform get/update/assoc using map/reduce. However, it 
 means that the code using this superstructure is taking a hit on 
 complexity/maintenance each time a non-map layer must be crossed. Of 
 course, the simplicity/beauty of the current implementation is that a path 
 can point to at most one target substructure/value. Is there a way to do 
 something similar with a more general definition of a path? One would 
 assume that it is something that might be handled by xml/html modification 
 libraries (think xpath or css selector) but this problem is more general 
 and not domain specific. Is there a clean library that handle that case 
 without being tied to html/xml?

 2) How to deal with more general superstructure like a graph?

 One could build an immutable graph but I don't believe it is something 
 that can be done by nesting immutable maps and vectors. One solution to 
 deal with 'entity'--'entity' relationships is for one of the member to own 
 only an identifier to get the other member from another reference structure.

 (from the basic OM tutorial:)

 {:people
  [{:type :student :first Ben :last Bitdiddle}
   {:type :professor :first Gerald :last Sussman :classes [:6001 
 :6946]}]
  :classes
  {:6001 The Structure and Interpretation of Computer Programs
   :6946 The Structure and Interpretation of Classical Mechanics
   :1806 Linear Algebra}}


 It is, of course, again, manually possible to get/update/assoc using 
 map/reduce.  But then, again, this is the same problematic as with the 
 first question : each time a relation needs to be crossed, the code using 
 this superstructure is taking a hit on complexity/maintenance. How do you 
 usually deal with this problematic?

 For both question 1) and 2), a more appropriate data structure might be 
 the answer like a graph/semantic-like store (Datomic or something else). 
 The questions are about intermediary solutions which would be less heavier.

 3) How does Demeter lives with graph traversal?

 This law is often heard in the OOP world but it is a bit more general than 
 that. When a long path on a superstructure is specified then if one 
 intermediary layer is introduced later, all hardcoded paths will be broken 
 ie in multiple locations in the code base. One would like to store local 
 structure knowledge in a single place. How do you usually deal with this 
 problematic?

 I have yet to take a serious look at lenses and their composition, they 
 are probably an element of answer, but they are more often seen in more 
 statically typed langage.

 Thanks for any feedback.

 Bertrand


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread François Rey

On 10/07/14 10:26, Bertrand Dechoux wrote:
For both question 1) and 2), a more appropriate data structure might 
be the answer like a graph/semantic-like store (Datomic or something 
else). The questions are about intermediary solutions which would be 
less heavier.


I would suggest you look into the walk 
http://clojuredocs.org/clojure_core/clojure.walk/walk/prewalk 
http://clojuredocs.org/clojure_core/clojure.walk/prewalk/postwalk 
http://clojuredocs.org/clojure_core/clojure.walk/postwalk functions. 
These are able to traverse arbitrary nested data structures while 
building a different or modified data structure.



3) How does Demeter lives with graph traversal?

This law is often heard in the OOP world but it is a bit more general 
than that. When a long path on a superstructure is specified then if 
one intermediary layer is introduced later, all hardcoded paths will 
be broken ie in multiple locations in the code base. One would like to 
store local structure knowledge in a single place. How do you usually 
deal with this problematic?


I have yet to take a serious look at lenses and their composition, 
they are probably an element of answer, but they are more often seen 
in more statically typed langage.


The walk http://clojuredocs.org/clojure_core/clojure.walk/walk/prewalk 
http://clojuredocs.org/clojure_core/clojure.walk/prewalk/postwalk 
http://clojuredocs.org/clojure_core/clojure.walk/postwalk can support 
some resilience with respects to structural changes if one can recognize 
what any data structure represents at any level based on its content 
(e.g. a :type key).


--
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups Clojure group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread Daniel Neal
 Is there a way to do something similar with a more general definition of 
a path? 

The lens library Fresnel (https://github.com/ckirkendall/fresnel) might be 
worth a look - it abstracts
get-in/assoc-in into lenses which can store/retrieve state from complex 
structures (and can be composed). 

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread Bertrand Dechoux
*@*Thomas Heller: It's a bit cleaner indeed. That way, a 'join-like' 
operation does not need to know about the structure. But the three 
problematics from my post are still unsolved.

*@Francois Rey:* I believe walk/prewalk/postwalk (and zipper?) might be the 
building blocks for implementing query/update based on a more flexible path 
definition. But by themselves, they are a bit low level. They indeed are 
beautiful and useful abstractions but I think another abstraction, even 
higher, could be built.

*@Daniel Neal:* I will look into it. I am new to lenses as I said. I don't 
know if a lens can target multiple structures at once (first question).

(def s { :key1 [{ :key2 { :key3 val } }]})
(update-in s [:key1 :all :key2 :key3] inc)

The principle might work with a custom lens but I guess it is likely the 
implementation for the traversal must be changed in order to handle a 
sequence at each step. But at least I have a place where I can start from.

Bertrand


Le jeudi 10 juillet 2014 13:26:57 UTC+2, Daniel Neal a écrit :

  Is there a way to do something similar with a more general definition of 
 a path? 

 The lens library Fresnel (https://github.com/ckirkendall/fresnel) might 
 be worth a look - it abstracts
 get-in/assoc-in into lenses which can store/retrieve state from complex 
 structures (and can be composed). 


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread François Rey
Also of interest is datomic datalog on regular clojure data structures 
and records:

https://gist.github.com/stuarthalloway/2645453
https://gist.github.com/stuarthalloway/3068749

--
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups Clojure group.

To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: 101 on simple and flexible graph query/update?

2014-07-10 Thread Frank Castellucci
Bertrand

I've been doing a lot of Ontology (OWL) with directed graphs (with cycles) 
and DAGS. One application we went with the nested map structure however now 
that I've been working on a normalized BPMN/XPDL utility 
( https://github.com/FrankC01/tributary ) I'm becoming enamored with the in 
XML format produced by xml-parse and then zipping it up. Coupled with 
clojures 'functional' nature, zippers become your friend really quickly and 
provide a most generic way of dealing with any graph with any number of 
layers.

The next step will be a normalized DSL on top of the zippers and using 
things like hickory-parse/data.zip selector concepts.

For the Ontology work we use datomic as the persist mechanism.



On Thursday, July 10, 2014 4:26:33 AM UTC-4, Bertrand Dechoux wrote:

 Hi,

 I have various general questions about how one can perform simple and 
 flexible graph query/update.

 If we start by a structure being nested maps then I know about 
 get-in/update-in/assoc-in. The common point about these functions is that 
 they all take a path to where the data is in the superstructure and that 
 this path is only a sequence of keys, which may or not be symbols.

 1) What happens when one layer of this superstructure is not a map but a 
 sequence? For the sake of the argument, we can keep the discussion simple 
 by only arguing about the vector case.

 Typically instead of
 { :key1 { :key2 val }}

 we now have
 { :key1 [{ :key2 val }]}

 Of course, one can perform get/update/assoc using map/reduce. However, it 
 means that the code using this superstructure is taking a hit on 
 complexity/maintenance each time a non-map layer must be crossed. Of 
 course, the simplicity/beauty of the current implementation is that a path 
 can point to at most one target substructure/value. Is there a way to do 
 something similar with a more general definition of a path? One would 
 assume that it is something that might be handled by xml/html modification 
 libraries (think xpath or css selector) but this problem is more general 
 and not domain specific. Is there a clean library that handle that case 
 without being tied to html/xml?

 2) How to deal with more general superstructure like a graph?

 One could build an immutable graph but I don't believe it is something 
 that can be done by nesting immutable maps and vectors. One solution to 
 deal with 'entity'--'entity' relationships is for one of the member to own 
 only an identifier to get the other member from another reference structure.

 (from the basic OM tutorial:)

 {:people
  [{:type :student :first Ben :last Bitdiddle}
   {:type :professor :first Gerald :last Sussman :classes [:6001 
 :6946]}]
  :classes
  {:6001 The Structure and Interpretation of Computer Programs
   :6946 The Structure and Interpretation of Classical Mechanics
   :1806 Linear Algebra}}


 It is, of course, again, manually possible to get/update/assoc using 
 map/reduce.  But then, again, this is the same problematic as with the 
 first question : each time a relation needs to be crossed, the code using 
 this superstructure is taking a hit on complexity/maintenance. How do you 
 usually deal with this problematic?

 For both question 1) and 2), a more appropriate data structure might be 
 the answer like a graph/semantic-like store (Datomic or something else). 
 The questions are about intermediary solutions which would be less heavier.

 3) How does Demeter lives with graph traversal?

 This law is often heard in the OOP world but it is a bit more general than 
 that. When a long path on a superstructure is specified then if one 
 intermediary layer is introduced later, all hardcoded paths will be broken 
 ie in multiple locations in the code base. One would like to store local 
 structure knowledge in a single place. How do you usually deal with this 
 problematic?

 I have yet to take a serious look at lenses and their composition, they 
 are probably an element of answer, but they are more often seen in more 
 statically typed langage.

 Thanks for any feedback.

 Bertrand


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.