* Type problem... possible design problem @ 2004-12-18 0:42 chris.danx 2004-12-18 4:00 ` [Caml-list] " Matt Gushee 2004-12-18 8:07 ` Jon Harrop 0 siblings, 2 replies; 8+ messages in thread From: chris.danx @ 2004-12-18 0:42 UTC (permalink / raw) To: O'Caml Mailing List Hi, What is the solution to the following problem? There are two types of object in a scene graph, those that may have children and those may not. A leaf may not have children. For various reasons, I need to preserve the methods of internal nodes (non leaves). I thought about something like this type childNode = LeafNode of sgLeaf | IntNode of sgInternal and class sgLeaf = object(self) method draw () = () end and class sgInternal = object(self) method addChild (child : childNode) = () method getChildren () = ... method draw () = () end but this isn't legal O'Caml. The following also doesn't work. type childNode = LeafNode of <draw:unit -> unit; ..> | IntNode of <draw:unit -> unit; addChild: childNode -> unit; ..> I've not programmed in O'Caml for a while and am not yet fully comfortable with ocamls object system anyway, so I may be being silly. Can anyone shed some light on a solution to this? Basically I need to be able to call addChild, etc for internal nodes if they're not leaves so I need to remember whether the type contains only draw or it also contains addChild, etc. It will be clients that call operations like addChild, getChildren, ... Perhaps this is the wrong solution entirely. Thanks, Chris ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 0:42 Type problem... possible design problem chris.danx @ 2004-12-18 4:00 ` Matt Gushee 2004-12-18 8:07 ` Jon Harrop 1 sibling, 0 replies; 8+ messages in thread From: Matt Gushee @ 2004-12-18 4:00 UTC (permalink / raw) To: caml-list chris.danx wrote: > type childNode = LeafNode of sgLeaf | IntNode of sgInternal > and > class sgLeaf .... etc. ... > I've not programmed in O'Caml for a while and am not yet fully > comfortable with ocamls object system anyway, so I may be being silly. > Can anyone shed some light on a solution to this? This seems to me like a good case for class types. How about something like: class type leafType = object method draw : unit -> unit end class type ['a] internalType = object method addChild : 'a -> unit method getChildren : unit -> 'a list method draw : unit -> unit end type childNode = LeafNode of leafType | IntNode of childNode internalType Then, of course, you'll need to define concrete classes that fit the class type signatures and/or coerce objects to those types. I'm not sure this is the most elegant solution, but it is at least syntactically valid, and seems to do what you want. -- Matt Gushee Englewood, CO, USA ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 0:42 Type problem... possible design problem chris.danx 2004-12-18 4:00 ` [Caml-list] " Matt Gushee @ 2004-12-18 8:07 ` Jon Harrop 2004-12-18 14:28 ` chris.danx 1 sibling, 1 reply; 8+ messages in thread From: Jon Harrop @ 2004-12-18 8:07 UTC (permalink / raw) To: caml-list On Saturday 18 December 2004 00:42, chris.danx wrote: > What is the solution to the following problem? There are two types of > object in a scene graph, those that may have children and those may not. > A leaf may not have children. Could you redefine this as "There is one type of node in a scenegraph, which has an arbitrary number of children"? Leaf nodes are then nodes with zero children. > I've not programmed in O'Caml for a while and am not yet fully > comfortable with ocamls object system anyway, so I may be being silly. > Can anyone shed some light on a solution to this? Why are you using OO? Can you do what you want with modules and variant types more easily? Cheers, Jon. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 8:07 ` Jon Harrop @ 2004-12-18 14:28 ` chris.danx 2004-12-18 15:27 ` Richard Jones ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: chris.danx @ 2004-12-18 14:28 UTC (permalink / raw) To: Jon Harrop; +Cc: caml-list Jon Harrop wrote: > On Saturday 18 December 2004 00:42, chris.danx wrote: > >>What is the solution to the following problem? There are two types of >>object in a scene graph, those that may have children and those may not. >> A leaf may not have children. > > > Could you redefine this as "There is one type of node in a scenegraph, which > has an arbitrary number of children"? Leaf nodes are then nodes with zero > children. I could. The problem was that I wanted to enforce that leaf nodes are the only renderable objects and internal nodes are for grouping and state changes - lights, transformations, etc. >>I've not programmed in O'Caml for a while and am not yet fully >>comfortable with ocamls object system anyway, so I may be being silly. >>Can anyone shed some light on a solution to this? > > Why are you using OO? Can you do what you want with modules and variant types > more easily? I was using OO because I want to extend the nodes available. I suppose I can use closures. My concern with variants is sharing subgraphs in graphs, will they be shared or copied? ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 14:28 ` chris.danx @ 2004-12-18 15:27 ` Richard Jones 2004-12-18 20:06 ` chris.danx 2004-12-18 18:37 ` Jon Harrop 2004-12-20 11:50 ` skaller 2 siblings, 1 reply; 8+ messages in thread From: Richard Jones @ 2004-12-18 15:27 UTC (permalink / raw) To: chris.danx; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 938 bytes --] On Sat, Dec 18, 2004 at 02:28:09PM +0000, chris.danx wrote: > My concern with variants is sharing subgraphs in graphs, will they be > shared or copied? A tree structure like this should be stored shared: type 'a tree = Leaf of 'a | Node of 'a tree list You can prove this; for instance: # let n = ref 1;; val n : int ref = {contents = 1} # let t = Leaf n;; val t : int ref tree = Leaf {contents = 1} # let tree = Node [t; t];; val tree : int ref tree = Node [Leaf {contents = 1}; Leaf {contents = 1}] # n := 2;; - : unit = () # tree;; - : int ref tree = Node [Leaf {contents = 2}; Leaf {contents = 2}] Rich. -- Richard Jones. http://www.annexia.org/ http://www.j-london.com/ >>> http://www.team-notepad.com/ - collaboration tools for teams <<< Merjis Ltd. http://www.merjis.com/ - improving website return on investment http://subjectlink.com/ - Lesson plans and source material for teachers [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 15:27 ` Richard Jones @ 2004-12-18 20:06 ` chris.danx 0 siblings, 0 replies; 8+ messages in thread From: chris.danx @ 2004-12-18 20:06 UTC (permalink / raw) To: Richard Jones; +Cc: caml-list Richard Jones wrote: > On Sat, Dec 18, 2004 at 02:28:09PM +0000, chris.danx wrote: > >>My concern with variants is sharing subgraphs in graphs, will they be >>shared or copied? > > A tree structure like this should be stored shared: > > type 'a tree = Leaf of 'a | Node of 'a tree list > > You can prove this; for instance: > > # let n = ref 1;; > val n : int ref = {contents = 1} > # let t = Leaf n;; > val t : int ref tree = Leaf {contents = 1} > # let tree = Node [t; t];; > val tree : int ref tree = Node [Leaf {contents = 1}; Leaf {contents = 1}] > # n := 2;; > - : unit = () > # tree;; > - : int ref tree = Node [Leaf {contents = 2}; Leaf {contents = 2}] Hmm... this looks like it shows two subtrees hold the same reference but it does not to me look like it proves the structure is shared, only that references work as expected. Perhaps I can use type 'a sceneGraph = Leaf of 'a | IntNode of 'a * 'a sceneGraph list | SharedNode of 'a sceneGraph ref to achieve what I want. Chris ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 14:28 ` chris.danx 2004-12-18 15:27 ` Richard Jones @ 2004-12-18 18:37 ` Jon Harrop 2004-12-20 11:50 ` skaller 2 siblings, 0 replies; 8+ messages in thread From: Jon Harrop @ 2004-12-18 18:37 UTC (permalink / raw) To: caml-list; +Cc: chris.danx Ah yes, it's coming back to me now. I asked about this on the mailing list almost a year ago because I didn't understand it then. I don't completely understand it now but I can tell you what I learned. :-) My original scenegraph implementation was written without objects. I wanted to be able to extend the functionality without touching the original code so I converted the whole thing to using objects instead. Basically, I found that neither approach solves all of the problems and I ended up converting the code back to non-OO because I decided this was the better of the two. There are two ways you'll want to extend the functionality provided by your scenegraph library: 1. Add new types of node (e.g. a "glyph leaf node" to represent a character). 2. Add new functions which act over scenegraphs or node (e.g. a "render_selected" function for a graphical editor). If you choose OO then you can easily create a new node class type which inherits from the base node class type. However, I couldn't figure out how to define new functions which act over arbitrary node types as the necessary functionality was rarely provided by the objects' interface, requiring me to create a whole new bunch of objects each time I needed a new function. If you choose non-OO then you can add new node constructors by reusing the old constructors but you'll have to add a little extra code to every new function which resorts to the equivalent existing function. I defined the type of a node in the scene graph to be the variant type over the types of metadata held in leaves ('a), loners ('b) and groups ('c) (a loner is a node with one child, such as a transformation): type ('a, 'b, 'c) generic_node = GenericLeaf of 'a | GenericLoner of 'b * ('a, 'b, 'c) generic_node | GenericGroup of 'c * ('a, 'b, 'c) generic_node list You can reuse this definition when adding new node types by supplementing the variant type used as 'a, 'b or 'c with an extra constructor. Your new function can then call the old function for the old contructor(s), thus reusing the old code. For example, I've then done: type basic_leaf = ContourObject of ContourObject.t type basic_loner = Transform of mat | Text of string * string type basic_group = Group of Bound.t cache type basic_node = (basic_leaf, basic_loner, basic_group) generic_node So basic_node is now a simple scenegraph which implements contour objects at the leaves, transforms and text as loners, and groups. A type of scenegraph which implements additional stuff (which I've done for the vector graphics editor) can either be defined similarly to the above (copying most of the code) or by referring back to the code above (which requires the same amount of code in this case and is less readable). However, functions which traverse the scenegraph can now be written straightforwardly. Of course, this looks like a tree and not a graph. I chose to implement the graphness by using "thin" metadata in the above variant types. In order to reuse a subgraph, the metadata contains a reference to a reference to a scenegraph, which can then be shared between nodes in the root scenegraph. This satisfies my design criteria but may not satisfy yours. In summary, I decided that users will not be adding layer upon layer of new node types and, consequently, the benefits associated with using variant types over OO outweighed the costs. I'd like to know if polymorphic variants would offer an improvement because they might be able to let you extend the variant type and resort to previously defined functions for the previously defined subset of the polymorphic variant's constructors. I can't see how they can but I've got a paper on extensible programming using polymorphic variants by someone (Jacques, no doubt ;-) which I have yet to absorb. As OCaml is a functional language, data tends to be magically shared (see "referential transparency") so you don't need to worry about this as long as you build each subgraph once and place it in two different parts of the scenegraph, it will be shared and not copied. Just don't build it twice. I'm very interested to hear what people have to say about this... HTH. Cheers, Jon. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Type problem... possible design problem 2004-12-18 14:28 ` chris.danx 2004-12-18 15:27 ` Richard Jones 2004-12-18 18:37 ` Jon Harrop @ 2004-12-20 11:50 ` skaller 2 siblings, 0 replies; 8+ messages in thread From: skaller @ 2004-12-20 11:50 UTC (permalink / raw) To: chris.danx; +Cc: Jon Harrop, caml-list On Sun, 2004-12-19 at 01:28, chris.danx wrote: > My concern with variants is sharing subgraphs in graphs, will they be > shared or copied? It is up to you. Consider: match ex with | `A a -> `A a | (`B b ) as x -> x | x -> x In the first case, you're making a new object, by executing the constructor `A. In the second and third you're not. In all cases, the constructor argument is shared. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2004-12-20 11:50 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-12-18 0:42 Type problem... possible design problem chris.danx 2004-12-18 4:00 ` [Caml-list] " Matt Gushee 2004-12-18 8:07 ` Jon Harrop 2004-12-18 14:28 ` chris.danx 2004-12-18 15:27 ` Richard Jones 2004-12-18 20:06 ` chris.danx 2004-12-18 18:37 ` Jon Harrop 2004-12-20 11:50 ` skaller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox