You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(18) |
Sep
(6) |
Oct
|
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
|
Feb
(4) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
(7) |
Sep
|
Oct
|
Nov
|
Dec
(2) |
From: Mike R. <mik...@gm...> - 2008-12-31 20:40:20
|
Quick update: I've added comments in the test code and documentation in all the regular code -- including documentation on how Sooc's generic code works. -Mike |
From: Mike R. <mik...@gm...> - 2008-12-31 02:33:54
|
The rewrite of Sooc from scratch is underway. The first commit was posted yesterday in the "rewrite" branch. The real code is for generic expanding arrays. This whole test driven development thing is working fairly well so far. Running "make check" delivers a very pleasant PASS. :) So Dan, if you'd like to help out, one thing you might do is evaluate the quality of the tests I've written. Indeed, this might be easier than evaluating the quality of my code directly! Next stop: threading & exceptions. -Mike |
From: Daniel R. <de...@vi...> - 2008-08-09 03:17:10
|
Sooc appears to compile just fine on vanilla 10.5 Leopard. Fink is no longer required strictly for downloading and compiling the sooc library. With the OS and the Xcode suite installed, all libraries necessary for compilation appear to be available by default. This includes the autotools (in the past, I recall it being somewhat difficult to obtain a recent enough copy of this package). One program that is a little tricky is "libtoolize." OS X does not include this; however, it does have glibtoolize, which by all accounts is the same thing. The user has a few options to get around this: (1) Edit ./bootstrap to change the command, (2) create an alias in .profile, (3) create a symlink somewhere in $PATH. Perhaps this OS X-specific scenario could be addressed in the bootstrap script itself? For instance, could it try "libtoolize" and then, if unsuccessful, try "glibtoolize?" It seems that this would, theoretically, account for other POSIX systems that use this version of the package. What do you think? So aside from determining how to get around the libtoolize thing, compiling is quite straightforward. Next, I have not specifically tested the linking of sooc applications with the sooc library (since I don't have a sooc application to test). However, what I do know is that Leopard appears not to have /etc/ld.so.conf. I think that /usr/local/lib is searched by default anyhow based on something I saw through Google. I have a number of libraries related to LaTeX already installed in /usr/local/lib, and that all seems to work fine. It's * possible* that the LaTeX installation did something to make the local libraries available, but I suspect they simply were from the start. Finally, pkg-config is not part of the vanilla OS install. Sooc's configuration script does not need it, but sooc does provide a .pc file, as I recall. So, if someone *chooses* to use that file when compiling a sooc program, then pkg-config will need to be obtained. *So, in summary, here are the steps to compile, install, and use sooc on Leopard:* 1) User must substitute glibtoolize for libtoolize 2) User may then run ./bootstrap and the compilation sequence 3) User probably does not have to update the library search path (it doesn't exist anyhow) 4) User should still need to run sudo ldconfig after updates. 5) User will need to obtain pkg-config (e.g. through "fink" or "macports") if user wishes to use this in future config scripts for applications that link to the sooc library Meanwhile, if the user is compiling under previous versions of OS X, it may be necessary to download additional dependencies through fink or macports. In the past, I believe I have used fink to obtain up-to-date versions of the autotools, pkg-config, and (I think) libtoolize. Again, however, the only thing that appears to be missing from 10.5 is pkg-config, and this isn't even required for compiling the library. In other words, the status is good ;-) Next thing is to actually run a test program, but I don't have one... |
From: Mike R. <mik...@gm...> - 2008-08-08 06:10:01
|
On Fri, Aug 1, 2008 at 1:04 AM, Daniel Reinish <sta...@gm...> wrote: > It's been a while since I've verified that Sooc compiles on OS X. > In particular, I can't remember if it's even ever been tested on > Leopard. Considering that a number of things changed since 10.4, > including full Unix certification, it will be interesting to see > what sort of process is involved in getting things working out of > the box. In particular, I'm wondering what sort of tools and > libraries still need to be obtained through sources like Fink > (probably the same ones as always, including but not limited to the > autotools). I don't have access to the dev tools at the moment, > since it's not worth installing them on my laptop. But I will take > a look at this some time soon when I set my desktop up again. At some point, Sooc should be mature enough to start growing in scope. That is, there should be Sooc interfaces for existing libraries. Most likely these will be built slowly and by demand. In any case, I think it'd be neat to set it up to configure those automatically. That is, the configure script should detect the presence of other libraries and decide whether to build the wrapper interface intelligently. Of course, you should be able to explicitly disable these as well. I've noticed that Pidgin does a good job of such automatic configuration, so we can look at that when the time comes. > When I do get a chance to do this, I think I will try to document, > for the sake of having it out there, what exactly needs to be done > to compile on OS X. That is to say, exactly what needs to be > downloaded, what settings need to be changed (if any), and so on? To build Sooc, I think you just need a POSIX-compliant C library including pthreads. You may also need pkg-config, or you may only need pkg-config if you want to use it later to compile and link more easily against Sooc. However, I think many systems need /usr/local/lib to be added to /etc/ld.so.conf in order to start Sooc programs at runtime. After installing a new version (like a new release) of Sooc, you need to run sudo ldconfig to make sure your linker knows what's happening. Also, in order to use Sooc's pkg-config, I needed to make sure the following was set: PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" In Gentoo, I just dropped that in /etc/env.d/999local-pkgconfig. On other systems, that goes in /etc/profile or somewhere... These system-wide tweaks apply whenever you build your first non-package-managed software installed to /usr/local. |
From: Mike R. <mik...@gm...> - 2008-08-08 05:53:55
|
On Fri, Aug 1, 2008 at 12:56 AM, Daniel Reinish <sta...@gm...> wrote: > Second: It's interesting that the node class is defined and > implemented in the same files as the map class. I actually didn't > realize you could do that in sooc, but due to C's procedural nature, > I guess that makes sense (and of course it's legal in other OO > languages). In fact, declaring multiple classes in one header is simple enough. However, defining multiple classes in one implementation file is a rather non-trivial aspect of Sooc. When we went from s_class { ... }; to s_class (x,y) { ... }; there were *major* changes required to ensure that all the code in the implementation would know what was the current class (I can't believe it all actually *works*!). But now, the bottom line for coding classes is that after the first class implementation in a .c file, you must do #undef SCurrentType #define SCurrentType TheSecondClass before all subsequent class implementations (the #undef is technically not necessary but it suppresses redefinition warnings). It's ok, but not required, to #define SCurrentType The FirstClass before the first class implementation for consistency. > I suppose it was done this way because SBSTreeNode is integral to > the functionality of SMap. It deserves pointing out, though, that > SBinaryNode, which is integral to the functionality of SLinkedList, > has its own file. So this leads me to two questions: (1) Would > SBSTreeNode ever be useful to classes other than SMap, meaning > things might be more clear if it had its own file? (2) Could > SBSTreeNode have benefited from being a subclass of SBinaryNode (or > vice versa) since they do seem to share some ideas conceptually? I was admittedly in a bit of a rush to code SMap. As a result, I didn't take much time to consider the design of SBSTreeNode. However, it is possible that it should be a subclass of SBinaryNode (specifically, one with a "parent" pointer that runs back up the tree). I need to review SBinaryNode, but I think it does some memory management stuff essential to the workings of SLinkedListIter. Maybe that functionality will come in handy for SMapIter at some point. In any case, as the status of SBSTreeNode is not yet clear, I've moved the whole thing into s-map.c so that it's not publicly exposed. When the design is settled, it can be refactored as necessary. > Regarding the latter question, I see that the biggest difference > regarding the way binary nodes and binary search tree nodes are > linked in sooc is that SBinaryNode uses a public data member whereas > SBSTreeNode uses a method that retrieves a private data member. > Presumably the public data member is faster since it doesn't require > whatever overhead occurs in calling a sooc method. On the other > hand, this might be an inconsistency, but I'm not sure. I definitely think these things should be done in a consistent way. In general, we are sticking to the get/set paradigm. I can't think of any reason to do SBSTreeNode differently, off the top of my head. > Third: I see that data2 (I think) is what holds the actual data that > is tied to the given key. What does the plain "data" member do? I > was having some trouble following the code that uses it. Because I wasn't sure how general SBSTreeNode should be, I tried to make it "somewhat general". In reality, it's map specific -- it needs to have a key and some data. As it stands, this thing should be SMapNode, and data should be key, and data2 should be data. It's a little sloppy. > On a related note, could you possibly explain in "laymen's terms" > how your binary search tree and map implementation works? I have a > general idea from the code, but it would be helpful to get the full > picture, so to speak. An important feature of keys is that they are of types implementing SComparable. Given one and another, you can always tell if they are equal, or if they are given in left-to-right order or right-to-left order. (So 1,2 would be left-to-right and 5,-3 would be right-to-left.) Start with the current node being the root node and with some given key. Compare the current node's key and the given key. If they match, you're there -- now you can get/set the corresponding data. If they are left-to-right order, run the same routine on root->right. If they are right-to-left order, run the same routine on root->left. This is generally much faster than, for example, traversing a list linearly in search of the key. Anyway, for a node, node->left = node->right = NULL at initialization. This way you can find the "leaves" in the tree. If you are trying to add a new key and some data, you can create a new node and affix it to an existing node's left or right. > Fourth: Related to the question above, I am unclear as to the > purpose of the "up" member of SBSTreeNode. From what I can tell, > only "left" and "right" are used to build a map (which makes sense). > I'm guessing "up" is intended for branching purposes. The name > SBSTreeNode implies that these nodes can be used to build a tree > with multiple nodes attached to one root, rather than simply being a > very fancy linear linked list. SMap clearly is not intended to have > this functionality, so it doesn't make use of the "up" link. If my > understanding is correct, might this be another reason for > SBSTreeNode to be its own file, since it might be used by more > complex collections later down the line? The idea is that just as you can recursively descend into the tree, you can recursively ascend it as well. Nonetheless, I've begun to think that only traversing functions, and not the structure itself, would ever need to keep track of the path back "up". I think I'll remove that member. > Fifth: How come set_up does not feature all the releasing and > retaining that takes place in set_left and set_right? Is this an > oversight or intentional? If intentional, could you explain the > rationale? In general, objects should not retain each other. If they did, they would become permanent! Therefore, while a parent node should retain its children, child nodes should not retain their parents. This probably won't matter though, since the "up" member will probably be scrapped in the absence of a strong argument for "retaining" it ;) Glad to see someone's poking around my code -- it helps keep me on my toes! Happy Soocing, -Mike |
From: Mike R. <mik...@gm...> - 2008-08-02 07:46:51
|
On Thu, Jul 31, 2008 at 11:55 PM, Daniel Reinish <sta...@gm...> wrote: > I was just wondering if there is any way around the need to have > separate sooc objects for every type of functor (i.e. a new object > each time a functor with more variables is needed). I'm guessing you > created SFunc1 when a simple functor was needed and recently created > SFunc2 due to the need for a pointer to some function with two > inputs. These function objects are, of course, useful to have > around, but it seems *somewhat* arbitrary that functors can only > support one or two arguments (obviously, these are two of most > likely argument counts). Yes, recently I (mistakenly) thought that I would need an SFunc2, so I ripped off SFunc1 to make SFunc2. I think it would be reasonable to include SFunc1-SFunc5. > My initial suspicion is that this is a limit of C. I know it's possible to > have a variable number of same-type parameters (I forget the technical name > for this) in Java and I'm guessing that if Java can do it, so can C++ (in > fact, we may have even talked about this before). I also suspect it would > be non-trivial to implement such a thing in Sooc, so I imagine that's why it > has not been done. Is that indeed the case? Is it possible at all? And, > the big question: does it even matter? In C and C++, you can have variadic functions (functions with a variable number/type of arguments) -- think printf(). The trick is that there needs to be some way of knowing where the argument list ends. Maybe you keep looking for integer/string pairs until the integer is -1, for example. Or maybe you keep looking for pointers until one is NULL (like s_retains() and s_releases(), for example). The point is, C/C++ variadic functions are extremely general, but consequently they are not type-safe. Anyway, there should probably be a SVFunc functor class, but I need to think more carefully about the design due to the tricky nature of variadic functions. > This is *clearly* not a priority at the moment, but if you think > there should be more, I would gladly write them myself, as it would > not be very complicated to simply copy the code and extend it where > necessary. As mentioned above, SFunc3-5 should probably be done. If you could handle that, it's less work for me -- good times! > And one last question. Why does the pointer message and related method need > to take the function's parameters as arguments? It doesn't seem to use them > since it merely returns a pointer to the function. Has this been done to > account for possible subclasses that may wish to re-connect the message to > some method that does do something with the arguments (although I can't > imagine what)? That is exactly the reason. I'm not sure if that would even be a reasonable thing to do, though. Maybe we should discuss that aspect of the design a little more.... It might be best to drop the argument list from the pointer method. -Mike |
From: Daniel R. <sta...@gm...> - 2008-08-01 05:04:13
|
It's been a while since I've verified that Sooc compiles on OS X. In particular, I can't remember if it's even ever been tested on Leopard. Considering that a number of things changed since 10.4, including full Unix certification, it will be interesting to see what sort of process is involved in getting things working out of the box. In particular, I'm wondering what sort of tools and libraries still need to be obtained through sources like Fink (probably the same ones as always, including but not limited to the autotools). I don't have access to the dev tools at the moment, since it's not worth installing them on my laptop. But I will take a look at this some time soon when I set my desktop up again. When I do get a chance to do this, I think I will try to document, for the sake of having it out there, what exactly needs to be done to compile on OS X. That is to say, exactly what needs to be downloaded, what settings need to be changed (if any), and so on? Because, you know, this is the sort of thing English teachers do in their spare time... Write documents... Yeah, that's the ticket... |
From: Daniel R. <sta...@gm...> - 2008-08-01 04:56:20
|
Some thoughts on SMap. First: Maps seem pretty cool in general. I once used ObjC's NSDictionary class, which is a lot like a map, in that it associates keys of some type with data of some type. Second: It's interesting that the node class is defined and implemented in the same files as the map class. I actually didn't realize you could do that in sooc, but due to C's procedural nature, I guess that makes sense (and of course it's legal in other OO languages). I suppose it was done this way because SBSTreeNode is integral to the functionality of SMap. It deserves pointing out, though, that SBinaryNode, which is integral to the functionality of SLinkedList, has its own file. So this leads me to two questions: (1) Would SBSTreeNode ever be useful to classes other than SMap, meaning things might be more clear if it had its own file? (2) Could SBSTreeNode have benefited from being a subclass of SBinaryNode (or vice versa) since they do seem to share some ideas conceptually? Regarding the latter question, I see that the biggest difference regarding the way binary nodes and binary search tree nodes are linked in sooc is that SBinaryNode uses a public data member whereas SBSTreeNode uses a method that retrieves a private data member. Presumably the public data member is faster since it doesn't require whatever overhead occurs in calling a sooc method. On the other hand, this might be an inconsistency, but I'm not sure. I assume that because LinkedList is such a basic data structure, it needed to be optimized for greatest speed/efficiency. SMap is much more esoteric data structure. Your thoughts on the differences between SBinaryNode and SBSTreeNode and whether they should be related would be appreciated! In addition, as mentioned before, your thoughts on whether SBSTreeNode should be its own file would also be appreciated. Third: I see that data2 (I think) is what holds the actual data that is tied to the given key. What does the plain "data" member do? I was having some trouble following the code that uses it. On a related note, could you possibly explain in "laymen's terms" how your binary search tree and map implementation works? I have a general idea from the code, but it would be helpful to get the full picture, so to speak. Fourth: Related to the question above, I am unclear as to the purpose of the "up" member of SBSTreeNode. From what I can tell, only "left" and "right" are used to build a map (which makes sense). I'm guessing "up" is intended for branching purposes. The name SBSTreeNode implies that these nodes can be used to build a tree with multiple nodes attached to one root, rather than simply being a very fancy linear linked list. SMap clearly is not intended to have this functionality, so it doesn't make use of the "up" link. If my understanding is correct, might this be another reason for SBSTreeNode to be its own file, since it might be used by more complex collections later down the line? Fifth: How come set_up does not feature all the releasing and retaining that takes place in set_left and set_right? Is this an oversight or intentional? If intentional, could you explain the rationale? Sixth: In s-map.h, the long description in the documentation for s_map_new refers to a parameter called key_klass; however, its actual name is key_rtti (I noticed that somewhere down the line you started using "rtti" in place of "klass." Some older files retain the previous convention.) While I'm pretty sure this is a typo, I chose not to modify it for now. The documentation for SMap is incomplete anyhow (I can probably write it at some point, if you'd like to continue focusing on code; as it stands, I think I already wrote a lot of the Collection documentation). Okay, I think that's all I have to say; sorry for saying so much. Nice work, as always! I hope my comments will prove useful. Let me know what you think, and I hope to hear from you soon! |
From: Daniel R. <sta...@gm...> - 2008-08-01 03:55:59
|
I decided to take a look at your recent sooc updates. I saw that one thing you did was to create a functor that takes 2 arguments. However, the included documentation, which was probably copied over from s-func1.h, kept saying it only took 1 argument. I corrected this and committed the changes. Please let me know (and fix it) if I have misunderstood this. Secondly, and this is the reason why I am sending this message to the mailing list and not to you directly, I was just wondering if there is any way around the need to have separate sooc objects for every type of functor (i.e. a new object each time a functor with more variables is needed). I'm guessing you created SFunc1 when a simple functor was needed and recently created SFunc2 due to the need for a pointer to some function with two inputs. These function objects are, of course, useful to have around, but it seems *somewhat* arbitrary that functors can only support one or two arguments (obviously, these are two of most likely argument counts). My initial suspicion is that this is a limit of C. I know it's possible to have a variable number of same-type parameters (I forget the technical name for this) in Java and I'm guessing that if Java can do it, so can C++ (in fact, we may have even talked about this before). I also suspect it would be non-trivial to implement such a thing in Sooc, so I imagine that's why it has not been done. Is that indeed the case? Is it possible at all? And, the big question: does it even matter? If functors of varying parameter counts are not possible (or important), how many of these things do you think there ought to be? Should it just stop at 2 or ought it to go out to 3 or 5 or something? This is *clearly* not a priority at the moment, but if you think there should be more, I would gladly write them myself, as it would not be very complicated to simply copy the code and extend it where necessary. And one last question. Why does the pointer message and related method need to take the function's parameters as arguments? It doesn't seem to use them since it merely returns a pointer to the function. Has this been done to account for possible subclasses that may wish to re-connect the message to some method that does do something with the arguments (although I can't imagine what)? Hope all is well and that your recent work on iterators and memory management and such has been coming along nicely. I will look at SMap next. |
From: Mike R. <mik...@gm...> - 2008-07-22 01:15:18
|
A possible alternative loop idiom is for (SIter* i = s_retain (s_iterable_get_iter (list)); !s_iter_is_end (i) || s_release (i); s_iter_advance (i)) { ... } Only after the last iteration, when s_iter_is_end() returns TRUE, would s_release() be called. Since the iterator will have a refcount of 1 before, it will be released to a refcount of 0, and freed. s_release() returns the pointer -- unless the object is freed, in which case it returns NULL. Therefore, the iterator would be freed and the OR expression would be false; the loop would be exited. Such an approach might be the "purist" approach. It still seems to me that taking the more pragmatic approach discussed earlier (automatically retaining and releasing), and recommending a sort of s_retain_forever() for the unusual cases, may ultimately be preferable. > Regarding the C89/C99 thing, I lost you a little bit. Will the new > code behave properly in both implementations? Sooc code itself does not assume that there exists something called "for" scope. All local variables are declared after an open brace and before any code that involves a function call. Therefore, the code should compile correctly on C89 compilers. However, gcc implements C99 correctly, and is the dominant choice on the target platforms (basically, Linux and OS X). Therefore, code that just uses Sooc may take advantage of the just-in-time declaration allowed by C99 (and C++, Java and other modern languages). In reality, most compilers in use today (gcc, MS cc) can probably be coaxed into accepting just-in-time declaration. Therefore, maybe even Sooc itself should use that convention. That's another subject, though. -Mike On Sun, Jul 20, 2008 at 4:53 PM, Daniel Reinish <sta...@gm...> wrote: > My initial impression was that the idea was a bit odd in that it > causes Iterators to behave differently from other standard sooc > objects. Upon further reflection, it may not be that different after > all. I forget exactly how garbage collection works internally, but > from the user's perspective, a non-retained object will disappear > "unpredictably." I use quotes since a little knowledge of the > systemcan give you an idea of whether you really need to retain > something. So, in this case, you can still retain an SIter if you > feel you need to; otherwise, it sticks around "at least" until the end > of the loop (in fact, that's exactly what it does). That seems fairly > intuitive: an SIter would be quite useless if it didn't last past the > first iteration, say. > > So, to me, it does feel natural. It definitely cleans up the code. > > > As for potential problems, I was unable to think of something other > than what you already described. So, let's see if I understand that > correctly. Suppose someone wants to use an SIter after the loop has > completed. Consequently, they make sure to retain it in the > declaration. The loop ends when s_iter_is_end() returns TRUE. > Internally, this causes s_release(), which cancels the internal > retain. The retain count is now 1. I don't know why they would do > this, but if the programmer continues to call s_iter_is_end(), they > could end up with I guess a segfault because eventually the object > will disappear. It's conceivable that this could occur because on the > surface, s_iter_is_end() appears to simply be an informational > accessor-like method rather than one that performs some sort of > complex task, like releasing the iterator. If one really needed to > use the iterator multiple times and repeatedly check whether it is at > the end, one would have to call s_retain() each time. > > I agree with you that generally speaking, an iterator is a one-use > object for dealing with one loop sequence. The question may be > whether there are any logical uses of iterators beyond the one-use > scenario. Also, even if there are not any logical uses, the fact > remains that one *can* use an iterator beyond the loop. Does the mere > fact that an iterator may persist beyond the loop (if properly > retained) mean this needs to be taken into account? I'm wondering if > this may indeed be so, simply because checking if the iterator has > reached its end doesn't seem at first like it should be a destructive > activity. So it seems like it's a question of accounting for > something somebody might actually want to do for some reason vs. > assuming that it will never happen. > > Two thoughts to add to the discussion: (1) Could this be solved > somehow using autorelease; and (2) would it be overkill to create a > special type of iterator (maybe SPersistentIter) for iterators that > don't want to die? > > > On Jul 18, 2008, at 7:53 PM, Mike Richman wrote: > >> In C++, for loops typically have the loop variable declared in the >> first part of the for(). For ordinary loops over integers and the >> like, this can be done in standard C as well -- that is, not C89, but >> in C99. However, until now, C99 could not simplify SIter loops; the >> SIter could be declared and retained inside the loop but there is no >> straightforward way of releasing it when the loop is over. >> >> For this reason, I am tentatively changing SIter retain/release >> policy. s_iterable_get_iter(), s_iterable_get_const_iter(), etc. will >> retain the new iterator before returning it. Then, when >> s_iter_is_end() or s_const_iter_is_end() is called and returns TRUE, >> it will release the iterator. A loop will go from this: >> >> >> SIter* i; >> for (i = s_retain (s_iterable_get_iter (some_list)); >> !s_iter_is_end (i); s_iter_advance (i)) { >> ... >> } >> s_release (i); >> >> >> to this: >> >> >> for (SIter* i = s_iterable_get_iter (some_list); >> !s_iter_is_end (i); s_iter_advance (i)) { >> ... >> } >> >> >> Even if C99 is not available (after all, Sooc tries to assume C89 with >> few extensions), the iterator need not be retained inside or released >> outside the loop. If you need the iterator to last, you can retain it >> and release it on your own terms. The only time this would be awkward >> is if the iterator needs to be used even after s_iter_is_end() has >> been called and has returned TRUE. However, in practice, this >> shouldn't be an issue -- that is, an iterator is normally a >> one-time-use device for iterating over a collection. >> >> What are some possible reasons why this may not be a good idea? Do >> you think it is a good idea? >> >> -Mike >> >> ------------------------------------------------------------------------- >> This SF.Net email is sponsored by the Moblin Your Move Developer's >> challenge >> Build the coolest Linux based applications with Moblin SDK & win >> great prizes >> Grand prize is a trip for two to an Open Source event anywhere in >> the world >> http://moblin-contest.org/redirect.php?banner_id=100&url=/ >> _______________________________________________ >> Sooc-devel mailing list >> Soo...@li... >> https://lists.sourceforge.net/lists/listinfo/sooc-devel > > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's challenge > Build the coolest Linux based applications with Moblin SDK & win great prizes > Grand prize is a trip for two to an Open Source event anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |
From: Daniel R. <sta...@gm...> - 2008-07-20 20:53:37
|
My initial impression was that the idea was a bit odd in that it causes Iterators to behave differently from other standard sooc objects. Upon further reflection, it may not be that different after all. I forget exactly how garbage collection works internally, but from the user's perspective, a non-retained object will disappear "unpredictably." I use quotes since a little knowledge of the systemcan give you an idea of whether you really need to retain something. So, in this case, you can still retain an SIter if you feel you need to; otherwise, it sticks around "at least" until the end of the loop (in fact, that's exactly what it does). That seems fairly intuitive: an SIter would be quite useless if it didn't last past the first iteration, say. So, to me, it does feel natural. It definitely cleans up the code. Regarding the C89/C99 thing, I lost you a little bit. Will the new code behave properly in both implementations? As for potential problems, I was unable to think of something other than what you already described. So, let's see if I understand that correctly. Suppose someone wants to use an SIter after the loop has completed. Consequently, they make sure to retain it in the declaration. The loop ends when s_iter_is_end() returns TRUE. Internally, this causes s_release(), which cancels the internal retain. The retain count is now 1. I don't know why they would do this, but if the programmer continues to call s_iter_is_end(), they could end up with I guess a segfault because eventually the object will disappear. It's conceivable that this could occur because on the surface, s_iter_is_end() appears to simply be an informational accessor-like method rather than one that performs some sort of complex task, like releasing the iterator. If one really needed to use the iterator multiple times and repeatedly check whether it is at the end, one would have to call s_retain() each time. I agree with you that generally speaking, an iterator is a one-use object for dealing with one loop sequence. The question may be whether there are any logical uses of iterators beyond the one-use scenario. Also, even if there are not any logical uses, the fact remains that one *can* use an iterator beyond the loop. Does the mere fact that an iterator may persist beyond the loop (if properly retained) mean this needs to be taken into account? I'm wondering if this may indeed be so, simply because checking if the iterator has reached its end doesn't seem at first like it should be a destructive activity. So it seems like it's a question of accounting for something somebody might actually want to do for some reason vs. assuming that it will never happen. Two thoughts to add to the discussion: (1) Could this be solved somehow using autorelease; and (2) would it be overkill to create a special type of iterator (maybe SPersistentIter) for iterators that don't want to die? On Jul 18, 2008, at 7:53 PM, Mike Richman wrote: > In C++, for loops typically have the loop variable declared in the > first part of the for(). For ordinary loops over integers and the > like, this can be done in standard C as well -- that is, not C89, but > in C99. However, until now, C99 could not simplify SIter loops; the > SIter could be declared and retained inside the loop but there is no > straightforward way of releasing it when the loop is over. > > For this reason, I am tentatively changing SIter retain/release > policy. s_iterable_get_iter(), s_iterable_get_const_iter(), etc. will > retain the new iterator before returning it. Then, when > s_iter_is_end() or s_const_iter_is_end() is called and returns TRUE, > it will release the iterator. A loop will go from this: > > > SIter* i; > for (i = s_retain (s_iterable_get_iter (some_list)); > !s_iter_is_end (i); s_iter_advance (i)) { > ... > } > s_release (i); > > > to this: > > > for (SIter* i = s_iterable_get_iter (some_list); > !s_iter_is_end (i); s_iter_advance (i)) { > ... > } > > > Even if C99 is not available (after all, Sooc tries to assume C89 with > few extensions), the iterator need not be retained inside or released > outside the loop. If you need the iterator to last, you can retain it > and release it on your own terms. The only time this would be awkward > is if the iterator needs to be used even after s_iter_is_end() has > been called and has returned TRUE. However, in practice, this > shouldn't be an issue -- that is, an iterator is normally a > one-time-use device for iterating over a collection. > > What are some possible reasons why this may not be a good idea? Do > you think it is a good idea? > > -Mike > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's > challenge > Build the coolest Linux based applications with Moblin SDK & win > great prizes > Grand prize is a trip for two to an Open Source event anywhere in > the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel |
From: Mike R. <mik...@gm...> - 2008-07-18 23:53:57
|
In C++, for loops typically have the loop variable declared in the first part of the for(). For ordinary loops over integers and the like, this can be done in standard C as well -- that is, not C89, but in C99. However, until now, C99 could not simplify SIter loops; the SIter could be declared and retained inside the loop but there is no straightforward way of releasing it when the loop is over. For this reason, I am tentatively changing SIter retain/release policy. s_iterable_get_iter(), s_iterable_get_const_iter(), etc. will retain the new iterator before returning it. Then, when s_iter_is_end() or s_const_iter_is_end() is called and returns TRUE, it will release the iterator. A loop will go from this: SIter* i; for (i = s_retain (s_iterable_get_iter (some_list)); !s_iter_is_end (i); s_iter_advance (i)) { ... } s_release (i); to this: for (SIter* i = s_iterable_get_iter (some_list); !s_iter_is_end (i); s_iter_advance (i)) { ... } Even if C99 is not available (after all, Sooc tries to assume C89 with few extensions), the iterator need not be retained inside or released outside the loop. If you need the iterator to last, you can retain it and release it on your own terms. The only time this would be awkward is if the iterator needs to be used even after s_iter_is_end() has been called and has returned TRUE. However, in practice, this shouldn't be an issue -- that is, an iterator is normally a one-time-use device for iterating over a collection. What are some possible reasons why this may not be a good idea? Do you think it is a good idea? -Mike |
From: Daniel R. <sta...@gm...> - 2008-02-24 21:49:04
|
Ah, interesting little hang-up. On Feb 24, 2008, at 4:36 PM, Mike Richman wrote: > I just thought of one additional problem. Right now, we tell Doxygen > that > > s_class (Derived, Base) > > means > > class Derived : Base > > With the new way, it will be rather more complicated to get Doxygen to > play nice with our classes. Still, I think that with an appropraite > Doxygen preprocessor script, it should be doable. I think it in a > sacrafice I am willing to make. > > I'll let you know when I take care of it. > > -Mike > > On Sun, Feb 24, 2008 at 3:50 PM, Daniel Reinish <sta...@gm... > > wrote: >> I'm not directly familiar with the structural changes that had to >> take place >> to make that system work. However, if reverting to the old >> technique will >> enable "always-on" data hiding as well as a system for wrapping >> messages in >> methods, those sound to me like two major reasons to do so. As you >> have >> pointed out before, the methods that get written for conveniently >> accessing >> the messages are rather inelegant. Furthermore, it has come to my >> attention >> in various conversations with you that data hiding has been a major >> headache >> for quite some time. That is rather unfortunate since it is a core >> principle of OO programming. Thus, while I'm kind of sad to see >> the loss of >> this aesthetically pleasing technique (which happens to bear a rather >> convenient resemblance to the way classes are defined in Objective- >> C), I can >> certainly understand the motivations to do away with it. >> >> An additional benefit that you have not mentioned is that it makes >> the >> meaning behind the declaration far more explicit. That is to say, >> the line >> "s_class (SObject, SBase)" for instance, does not inherently tell >> anything >> to the reader. In particular, deeper into the class hierarchy, it >> may not >> be entirely evident who is inheriting from whom. Explicit #define >> statements make it incredibly obvious which class is the current >> one and >> which is the parent. Having the words SType and SParent in the >> code is kind >> of unfortunate because it is not something one normally works with >> directly, >> but it is not altogether unreasonable or impractical. >> >> I really agree with you that the only significant con is that it >> doesn't >> look as nice and/or clever . You have implied in your explanation >> that >> reverting to the #define statements opens up a ton of additional >> flexibility. I would say that sacrificing prettiness that has >> resulted in >> some major roadblocks in the name of increased flexibility is a >> reasonable >> direction to go at this point, given that you have tried nearly >> everything >> imaginable to get around some of those roadblocks with little >> success. If >> the resulting technique were incredibly ugly, I'd have a problem >> with it. >> Two #define statements and the resulting removal of the explicit >> SHide >> business definitely does not fall into the category of incredibly >> ugly. >> >> Furthermore, I believe the underlying implementation could >> certainly do with >> some simplification. This is Simple Object-Oriented C, after all— >> and all >> those preprocessor macros and such are pretty crazy from my >> perspective. >> >> So, in conclusion, I support your decision. And, as this is part >> of the >> library's core functionality, this will obviously be something that >> needs to >> be accomplished before we tackle a Sooc implementation of Polar >> Connection >> or any other software. >> >> Good luck! >> >> --Dan >> >> >> >> On Feb 24, 2008, at 4:05 AM, Mike Richman wrote: >> >> >> It has become clear to me that the current mechanism for class >> declaration is no longer viable. While code like >> >> s_class (Derived, Base) { >> .... >> }; >> >> has a certain aesthetic appeal, it is no longer worth while. I'm >> still proud of the tricks I used to make it work, but ultimately the >> following will prove more effective and simple -- and thus in line >> with the principles of Sooc: >> >> #define SType SObject >> #define SParent SBase >> s_class { >> ... >> }; >> >> Pros: >> Will allow new techniques for wrapping messages in methods >> conveniently. >> Will simplify the underlying implementation by reducing the need for >> redundancy such as obscure pointers to Sooc-instantiated functions. >> Will not require the header author additionally to "#define SHide >> MyType" in order to enable data hiding; hence data hiding will always >> be possible. >> Will enable more flexible section ordering of s_class, etc. blocks. >> Probably the only requirement will be that methods (not members) come >> first, which is simpler and more sensible than the current required >> order. This will also allow somewhat less memory to be used by class >> metadata structures. >> Will potentially allow more flexible expansion that is not yet >> foreseen (indeed, failure to foresee the issues we are confronting to >> day is part of what led us to believe that the existing system was >> viable) >> >> Cons: >> Somewhat less cute. >> >> I think this top-of-the-head list is more than sufficient to show >> that >> we should revert to the #define technique that we used once upon a >> time. If you have anything to add to the pro/con list, do let me >> know. I will try to make this [fairly drastic] change in the near >> future. >> >> -Mike >> >> ------------------------------------------------------------------------- >> This SF.net email is sponsored by: Microsoft >> Defy all challenges. Microsoft(R) Visual Studio 2008. >> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ >> _______________________________________________ >> Sooc-devel mailing list >> Soo...@li... >> https://lists.sourceforge.net/lists/listinfo/sooc-devel >> >> >> ------------------------------------------------------------------------- >> This SF.net email is sponsored by: Microsoft >> Defy all challenges. Microsoft(R) Visual Studio 2008. >> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ >> _______________________________________________ >> Sooc-devel mailing list >> Soo...@li... >> https://lists.sourceforge.net/lists/listinfo/sooc-devel >> >> > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel |
From: Mike R. <mik...@gm...> - 2008-02-24 21:37:02
|
I just thought of one additional problem. Right now, we tell Doxygen that s_class (Derived, Base) means class Derived : Base With the new way, it will be rather more complicated to get Doxygen to play nice with our classes. Still, I think that with an appropraite Doxygen preprocessor script, it should be doable. I think it in a sacrafice I am willing to make. I'll let you know when I take care of it. -Mike On Sun, Feb 24, 2008 at 3:50 PM, Daniel Reinish <sta...@gm...> wrote: > I'm not directly familiar with the structural changes that had to take place > to make that system work. However, if reverting to the old technique will > enable "always-on" data hiding as well as a system for wrapping messages in > methods, those sound to me like two major reasons to do so. As you have > pointed out before, the methods that get written for conveniently accessing > the messages are rather inelegant. Furthermore, it has come to my attention > in various conversations with you that data hiding has been a major headache > for quite some time. That is rather unfortunate since it is a core > principle of OO programming. Thus, while I'm kind of sad to see the loss of > this aesthetically pleasing technique (which happens to bear a rather > convenient resemblance to the way classes are defined in Objective-C), I can > certainly understand the motivations to do away with it. > > An additional benefit that you have not mentioned is that it makes the > meaning behind the declaration far more explicit. That is to say, the line > "s_class (SObject, SBase)" for instance, does not inherently tell anything > to the reader. In particular, deeper into the class hierarchy, it may not > be entirely evident who is inheriting from whom. Explicit #define > statements make it incredibly obvious which class is the current one and > which is the parent. Having the words SType and SParent in the code is kind > of unfortunate because it is not something one normally works with directly, > but it is not altogether unreasonable or impractical. > > I really agree with you that the only significant con is that it doesn't > look as nice and/or clever . You have implied in your explanation that > reverting to the #define statements opens up a ton of additional > flexibility. I would say that sacrificing prettiness that has resulted in > some major roadblocks in the name of increased flexibility is a reasonable > direction to go at this point, given that you have tried nearly everything > imaginable to get around some of those roadblocks with little success. If > the resulting technique were incredibly ugly, I'd have a problem with it. > Two #define statements and the resulting removal of the explicit SHide > business definitely does not fall into the category of incredibly ugly. > > Furthermore, I believe the underlying implementation could certainly do with > some simplification. This is Simple Object-Oriented C, after all—and all > those preprocessor macros and such are pretty crazy from my perspective. > > So, in conclusion, I support your decision. And, as this is part of the > library's core functionality, this will obviously be something that needs to > be accomplished before we tackle a Sooc implementation of Polar Connection > or any other software. > > Good luck! > > --Dan > > > > On Feb 24, 2008, at 4:05 AM, Mike Richman wrote: > > > It has become clear to me that the current mechanism for class > declaration is no longer viable. While code like > > s_class (Derived, Base) { > .... > }; > > has a certain aesthetic appeal, it is no longer worth while. I'm > still proud of the tricks I used to make it work, but ultimately the > following will prove more effective and simple -- and thus in line > with the principles of Sooc: > > #define SType SObject > #define SParent SBase > s_class { > ... > }; > > Pros: > Will allow new techniques for wrapping messages in methods conveniently. > Will simplify the underlying implementation by reducing the need for > redundancy such as obscure pointers to Sooc-instantiated functions. > Will not require the header author additionally to "#define SHide > MyType" in order to enable data hiding; hence data hiding will always > be possible. > Will enable more flexible section ordering of s_class, etc. blocks. > Probably the only requirement will be that methods (not members) come > first, which is simpler and more sensible than the current required > order. This will also allow somewhat less memory to be used by class > metadata structures. > Will potentially allow more flexible expansion that is not yet > foreseen (indeed, failure to foresee the issues we are confronting to > day is part of what led us to believe that the existing system was > viable) > > Cons: > Somewhat less cute. > > I think this top-of-the-head list is more than sufficient to show that > we should revert to the #define technique that we used once upon a > time. If you have anything to add to the pro/con list, do let me > know. I will try to make this [fairly drastic] change in the near > future. > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > > |
From: Daniel R. <sta...@gm...> - 2008-02-24 20:50:37
|
I'm not directly familiar with the structural changes that had to take place to make that system work. However, if reverting to the old technique will enable "always-on" data hiding as well as a system for wrapping messages in methods, those sound to me like two major reasons to do so. As you have pointed out before, the methods that get written for conveniently accessing the messages are rather inelegant. Furthermore, it has come to my attention in various conversations with you that data hiding has been a major headache for quite some time. That is rather unfortunate since it is a core principle of OO programming. Thus, while I'm kind of sad to see the loss of this aesthetically pleasing technique (which happens to bear a rather convenient resemblance to the way classes are defined in Objective-C), I can certainly understand the motivations to do away with it. An additional benefit that you have not mentioned is that it makes the meaning behind the declaration far more explicit. That is to say, the line "s_class (SObject, SBase)" for instance, does not inherently tell anything to the reader. In particular, deeper into the class hierarchy, it may not be entirely evident who is inheriting from whom. Explicit #define statements make it incredibly obvious which class is the current one and which is the parent. Having the words SType and SParent in the code is kind of unfortunate because it is not something one normally works with directly, but it is not altogether unreasonable or impractical. I really agree with you that the only significant con is that it doesn't look as nice and/or clever. You have implied in your explanation that reverting to the #define statements opens up a ton of additional flexibility. I would say that sacrificing prettiness that has resulted in some major roadblocks in the name of increased flexibility is a reasonable direction to go at this point, given that you have tried nearly everything imaginable to get around some of those roadblocks with little success. If the resulting technique were incredibly ugly, I'd have a problem with it. Two #define statements and the resulting removal of the explicit SHide business definitely does not fall into the category of incredibly ugly. Furthermore, I believe the underlying implementation could certainly do with some simplification. This is Simple Object-Oriented C, after all—and all those preprocessor macros and such are pretty crazy from my perspective. So, in conclusion, I support your decision. And, as this is part of the library's core functionality, this will obviously be something that needs to be accomplished before we tackle a Sooc implementation of Polar Connection or any other software. Good luck! --Dan On Feb 24, 2008, at 4:05 AM, Mike Richman wrote: > It has become clear to me that the current mechanism for class > declaration is no longer viable. While code like > > s_class (Derived, Base) { > .... > }; > > has a certain aesthetic appeal, it is no longer worth while. I'm > still proud of the tricks I used to make it work, but ultimately the > following will prove more effective and simple -- and thus in line > with the principles of Sooc: > > #define SType SObject > #define SParent SBase > s_class { > ... > }; > > Pros: > Will allow new techniques for wrapping messages in methods > conveniently. > Will simplify the underlying implementation by reducing the need for > redundancy such as obscure pointers to Sooc-instantiated functions. > Will not require the header author additionally to "#define SHide > MyType" in order to enable data hiding; hence data hiding will always > be possible. > Will enable more flexible section ordering of s_class, etc. blocks. > Probably the only requirement will be that methods (not members) come > first, which is simpler and more sensible than the current required > order. This will also allow somewhat less memory to be used by class > metadata structures. > Will potentially allow more flexible expansion that is not yet > foreseen (indeed, failure to foresee the issues we are confronting to > day is part of what led us to believe that the existing system was > viable) > > Cons: > Somewhat less cute. > > I think this top-of-the-head list is more than sufficient to show that > we should revert to the #define technique that we used once upon a > time. If you have anything to add to the pro/con list, do let me > know. I will try to make this [fairly drastic] change in the near > future. > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel |
From: Mike R. <mik...@gm...> - 2008-02-24 09:05:36
|
It has become clear to me that the current mechanism for class declaration is no longer viable. While code like s_class (Derived, Base) { .... }; has a certain aesthetic appeal, it is no longer worth while. I'm still proud of the tricks I used to make it work, but ultimately the following will prove more effective and simple -- and thus in line with the principles of Sooc: #define SType SObject #define SParent SBase s_class { ... }; Pros: Will allow new techniques for wrapping messages in methods conveniently. Will simplify the underlying implementation by reducing the need for redundancy such as obscure pointers to Sooc-instantiated functions. Will not require the header author additionally to "#define SHide MyType" in order to enable data hiding; hence data hiding will always be possible. Will enable more flexible section ordering of s_class, etc. blocks. Probably the only requirement will be that methods (not members) come first, which is simpler and more sensible than the current required order. This will also allow somewhat less memory to be used by class metadata structures. Will potentially allow more flexible expansion that is not yet foreseen (indeed, failure to foresee the issues we are confronting to day is part of what led us to believe that the existing system was viable) Cons: Somewhat less cute. I think this top-of-the-head list is more than sufficient to show that we should revert to the #define technique that we used once upon a time. If you have anything to add to the pro/con list, do let me know. I will try to make this [fairly drastic] change in the near future. -Mike |
From: Dan R. <sta...@gm...> - 2007-09-03 14:32:51
|
Multiple interface types seems kind of hefty, but I'll let you think about it some more. On 9/3/07, Mike Richman <mik...@gm...> wrote: > > It sounds like there are good reasons for Sooc to have interfaces that > can have partial or (maybe) complete default implementations, and > other good reasons for Sooc to have interfaces that forbid default > implementations. Maybe it should allow both? > > I haven't thought this through completely, but maybe there can be > something like s_iface and s_pure_iface. Pure interfaces would forbid > any default implementations either by providing no means of connecting > handlers or by zeroing the whole iface at the end of its init > function. > > Also, regardless of how interfaces end up working, I think it might be > nice to have a debugging mode at runtime. It can be on or off. When > it's on, each class will track where its messages are connected. User > code could then do something like s_dbg_msg_connections (stream, > Class). There could potentially be other debugging help when > debugging mode is on. This message tracking will be non-trivial to > implement, though. > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |
From: Mike R. <mik...@gm...> - 2007-09-03 06:44:22
|
It sounds like there are good reasons for Sooc to have interfaces that can have partial or (maybe) complete default implementations, and other good reasons for Sooc to have interfaces that forbid default implementations. Maybe it should allow both? I haven't thought this through completely, but maybe there can be something like s_iface and s_pure_iface. Pure interfaces would forbid any default implementations either by providing no means of connecting handlers or by zeroing the whole iface at the end of its init function. Also, regardless of how interfaces end up working, I think it might be nice to have a debugging mode at runtime. It can be on or off. When it's on, each class will track where its messages are connected. User code could then do something like s_dbg_msg_connections (stream, Class). There could potentially be other debugging help when debugging mode is on. This message tracking will be non-trivial to implement, though. -Mike |
From: Dan R. <sta...@gm...> - 2007-09-03 04:19:46
|
Mike, Alright, so I actually looked at the code for SCloneable, and now I understand what you're talking about. The idea behind these default implementations is to allow messages to, by default, depend on other messages. One application, as you have demonstrated, is to minimize the number of messages an "implementor" actually needs to handle. As you explained before, all an object has to do to be fully cloneable is handle the "distinguish" method. The default handlers in the SCloneable interface take care of the various types of cloning. This is possible because the default handlers work with the memory directly without depending on the specifc methods or variables of a given object. So, this default implementation concept will work as long as the programmer is broad enough when writing them. It definitely works for SCloneable. I'd be a little nervous for other custom-made interfaces. One problem I can foresee is how this technique might encourages a programmer to lock an interface to a particular class hierarchy. In other words, a programmer may feel encouraged to create an interface with default handlers written in terms of SClock, expecting this interface to only be used for SClock and its children. This is sloppy programming of course, since it would make more sense to include Clock-specific code in SClock itself. Still, the programmer could abuse the interface system in this way if he/she wanted. This sort of interface-locking seems to border on multiple inheritance in the way it could force an interface to actually be part of the inheritance tree (albeit a very strange sort of branch). Okay, on second thought, it's not really locking. I neglected to consider the fact that the programmer has the option of implementing his own handlers for any message that has a default behavior. So, no matter what, an interface cannot be locked to a specific portion of the inheritance tree. Still, this doesn't change the fact that an interface can function, by default, as part of that tree. I'm not exactly sure what I think of this. Interfaces are very safe in Java in that they are merely frameworks. An interface will only be functional if a programmer makes sure to implement every piece of it. The programmer never has to think about what the interface will do if he chooses not to implement various pieces because it is simply useless in that state. In sooc, the programmer needs (or at least ought) to know how a particular interface behaves by default. He/she can change this behavior to suit his/her needs, but this is an extra decision that needs to be made each time an interface is implemented. And it becomes more confusing, I think, when the defaults don't assume SObject and only methods/messages associated with SObject. In any case, I'm not necessarily saying that what you've created is a bad idea. It's obviously relatively powerful in that you can essentially give a whole bunch of new functions to an object just by handling one message. I'm just wondering if what we have here is really that clean. In the case of SClone, SObject itself could implement the SCloneable messages in a manner identical to the current defaults. On the surface, this would result in the same functionality. Users would still only have to "override" the distinguish message in order to make deep clones work for a specific kind of child. In this model, interfaces remain simply frameworks, as in Java. It is up to various branches of the class hierarchy to determine the default behavior of an interface. And if there is a behavior that really ought to apply to allobjects, then it can simply be hard-coded into SObject. Children can still override these behaviors if required. The point is, the interface is free to remain a specification rather than a "suggested implementation," if you will. I wonder if it might be more in the spirit of sooc to limit default behaviors to class definitions. This way, a programmer is not encouraged to tie some behavior to the interface definition and then forget months later where it is indicated that Clocks should behave a certain way when the Strokeable::stroke message is called and GolfClubs seem to not understand how to do it by default (and, in fact, freak out because a Clock stroke has nothing to do with a golf stroke). (Srokeable is, of course, a horrible use of interfaces, but I think it helps explain my point.) Hopefully, I'm not grossly misunderstanding something here. So just take this as food for thought and eventually let me know what you think. --Dan P.S. Golfing should always be less dependent on time... On 9/2/07, Dan Reinish <sta...@gm...> wrote: > > I'm sorry...i'm a little confused by your explanation. > > On 9/2/07, Mike Richman <mik...@gm... > wrote: > > > > The thing about messages is that they are totally dynamic: you > > generally connect them in s_class_implement() or its brethren, but you > > can (re)connect them anywhere in the class implementation. So it > > seems to me that checking that all the messages are connected needs to > > be dynamic also. > > > > Regarding default implementations... some of an interface's default > > handlers can operate in terms of other messages (which may or may not > > have default handlers) of the same or of inherited interfaces. > > SCloneable /does/ assume that it's dealing with an SObject, but I feel > > like that's valid. Let me know if/why you disagree. > > > > -Mike > > > > > > ------------------------------------------------------------------------- > > This SF.net email is sponsored by: Splunk Inc. > > Still grepping through log files to find problems? Stop. > > Now Search log events and configuration files using AJAX and a browser. > > Download your FREE copy of Splunk now >> http://get.splunk.com/ > > _______________________________________________ > > Sooc-devel mailing list > > Soo...@li... > > https://lists.sourceforge.net/lists/listinfo/sooc-devel > > > > |
From: Dan R. <sta...@gm...> - 2007-09-02 18:05:23
|
I'm sorry...i'm a little confused by your explanation. On 9/2/07, Mike Richman <mik...@gm...> wrote: > > The thing about messages is that they are totally dynamic: you > generally connect them in s_class_implement() or its brethren, but you > can (re)connect them anywhere in the class implementation. So it > seems to me that checking that all the messages are connected needs to > be dynamic also. > > Regarding default implementations... some of an interface's default > handlers can operate in terms of other messages (which may or may not > have default handlers) of the same or of inherited interfaces. > SCloneable /does/ assume that it's dealing with an SObject, but I feel > like that's valid. Let me know if/why you disagree. > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |
From: Mike R. <mik...@gm...> - 2007-09-02 17:57:20
|
The thing about messages is that they are totally dynamic: you generally connect them in s_class_implement() or its brethren, but you can (re)connect them anywhere in the class implementation. So it seems to me that checking that all the messages are connected needs to be dynamic also. Regarding default implementations... some of an interface's default handlers can operate in terms of other messages (which may or may not have default handlers) of the same or of inherited interfaces. SCloneable /does/ assume that it's dealing with an SObject, but I feel like that's valid. Let me know if/why you disagree. -Mike |
From: Dan R. <sta...@gm...> - 2007-09-01 00:37:30
|
Is there a way, perhaps by using preprocessor defines or something, to check that interfaces have been implemented at compile time? Perhaps the compiler could spit out warnings (or halt?) if this were encountered? At least this way, the programmer would know if he/she were lazy and forgot to implement something. (Since, as we know, one use of interfaces is to keep the programmer on top of things.) As for default implementations, I'm a little confused. How can an interface have a default implementation if one doesn't know anything about the objects that can implement it? The interesting thing about interfaces is that they allow you to lump various objects together by the actions they perform even if they are not part of the same hierarchy. So I'm a little perplexed how what you have described works. I might just be missing something here, so please explain if you can. On 8/30/07, Mike Richman <mik...@gm...> wrote: > > My plan for checking for message handlers in instantiable classes will > not suffice. I implemented the algorithm completely, only to find > that I began with an incorrent implicit assumption. Specifically, I > assumed that sizeof (SomethingClass) would be exactly sizeof > (SBaseClass) + sizeof (all_its_interfaces) + number_of_messages * > sizeof (void*). No dice. For efficiency, compiler implementations > are allowed to pad structs, or leave extra space between members. For > example, I added some members to SFileClass, and then removed them, > but its size remained constant at 192 bytes. The result is that we > can't treat every set of 4 bytes as a pointer, as some bytes are > actually padding. > > As far as I can tell, this means that there is no way to check for all > message handlers at class initiation time. We have to wait till the > message is sent and then check if it is handled. This is bad for > speed when typechecking is on, but more importantly, it's bad for > catching errors earlier. Still, I'll try to think of a way. > > The good news is, the actual process of finding a message is now > optimized more effectively. Also, our interfaces now beat Java in > that we can provide default implementations. Take a look at the Java > docs for SObject.clone() and the Cloneable interface, and you can tell > it's a mess. You can also tell that the reason it's a mess is that > they want to include a default implementation of clone() but only for > Cloneable objects... It's definitely ugly. > > In our implementation, implementing SCloneable guarantees that you can > obtain a clone. To make it a deep clone, you just need to handle the > message SCloneable::distinguish, which lets you distinguish a clone > from the source object. This would typically be done by replacing > pointers to the source's member objects with pointers to fresh copies > of the source's member objects. (For example, SString's distinguish > allocates its own new character array and copies the source's string > there.) For a derived class to add to its parent class's distinguish > handler, it should handle SCloneable::distinguish with a function that > starts with something like s_super_msg (obj, SCloneable, distinguish). > s_super_msg() sends a message treating obj as the immediate parent > type of its actual type. This way, message handlers can chain up, > adding behavior rather than replacing it. > > So, it's great that we include default handlers, but it's definitely a > shame that we can't check for message handlers (yet?) at class > initiation time. > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |
From: Mike R. <mik...@gm...> - 2007-08-31 00:26:02
|
My plan for checking for message handlers in instantiable classes will not suffice. I implemented the algorithm completely, only to find that I began with an incorrent implicit assumption. Specifically, I assumed that sizeof (SomethingClass) would be exactly sizeof (SBaseClass) + sizeof (all_its_interfaces) + number_of_messages * sizeof (void*). No dice. For efficiency, compiler implementations are allowed to pad structs, or leave extra space between members. For example, I added some members to SFileClass, and then removed them, but its size remained constant at 192 bytes. The result is that we can't treat every set of 4 bytes as a pointer, as some bytes are actually padding. As far as I can tell, this means that there is no way to check for all message handlers at class initiation time. We have to wait till the message is sent and then check if it is handled. This is bad for speed when typechecking is on, but more importantly, it's bad for catching errors earlier. Still, I'll try to think of a way. The good news is, the actual process of finding a message is now optimized more effectively. Also, our interfaces now beat Java in that we can provide default implementations. Take a look at the Java docs for SObject.clone() and the Cloneable interface, and you can tell it's a mess. You can also tell that the reason it's a mess is that they want to include a default implementation of clone() but only for Cloneable objects... It's definitely ugly. In our implementation, implementing SCloneable guarantees that you can obtain a clone. To make it a deep clone, you just need to handle the message SCloneable::distinguish, which lets you distinguish a clone from the source object. This would typically be done by replacing pointers to the source's member objects with pointers to fresh copies of the source's member objects. (For example, SString's distinguish allocates its own new character array and copies the source's string there.) For a derived class to add to its parent class's distinguish handler, it should handle SCloneable::distinguish with a function that starts with something like s_super_msg (obj, SCloneable, distinguish). s_super_msg() sends a message treating obj as the immediate parent type of its actual type. This way, message handlers can chain up, adding behavior rather than replacing it. So, it's great that we include default handlers, but it's definitely a shame that we can't check for message handlers (yet?) at class initiation time. -Mike |
From: Dan R. <sta...@gm...> - 2007-08-26 21:02:59
|
You know my feelings on consistency. On 8/26/07, Mike Richman <mik...@gm...> wrote: > > I think Java has the right idea with their toString() method. Using > methods like toX() seems like a good pattern for all conversion > methods. Maybe it's time Sooc grows up a bit and changes 'stringify' > into 'to_string'. What do you think? > > -Mike > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > Sooc-devel mailing list > Soo...@li... > https://lists.sourceforge.net/lists/listinfo/sooc-devel > |
From: Mike R. <mik...@gm...> - 2007-08-26 06:04:12
|
I think Java has the right idea with their toString() method. Using methods like toX() seems like a good pattern for all conversion methods. Maybe it's time Sooc grows up a bit and changes 'stringify' into 'to_string'. What do you think? -Mike |