Comments By: Peter Goodman
-
I think I should simply put a message on this blog post for people to ignore it. I thought it was a clever hack at the time of writing it; however, in retrospect it is terrible advice.
posted on Jul 6, 2009 at 8:00am | context -
You are correct in that it doesn't necessarily follow that language X can describe itself. For example, if language X is inherently ambiguous and the language or the method used to parse languages according to its rules do not allow for ambiguity then language X simply won't suffice.
posted on Jun 20, 2009 at 12:47pm | context
Another problem relating to the aforementioned ambiguity problem would be if language X's description were to require context-sensitive things, where a word in language X means one thing in one context and another in a different context. If language X is a context-free language then my conclusion does not follow.
The main motivation of the post was to elicit excitement about parsing. I like the description I gave because it is high level enough (it ignores all thoughts about ambiguity, context, recursion, etc) to expose an interesting idea and because the idea itself is closed box (insofar as we don't get stuck in an infinite regress of one thing describing itself describing itself describing ...).
I don't think that I follow your thought in saying this sounds like set theory; could you please elaborate? It's more precise to say that language X can describe a subset of all languages, and if language X itself is within that subset then language X can describe itself; however, I don't feel like this is what you were alluding to. -
I think that PHP should keep the idea of unrecoverable error for parse errors, and in this case, they should try to continue parsing a file to find as many parse errors as they can.
posted on Mar 19, 2009 at 9:57am | context
I agree that for most other things, using exceptions as the main method for errors would be nice; however, I would add one thing, and this is somewhat inspired by the way Java lays things out (PHP would also current, or might actually, support this).
Most errors would actually extend Error, which implements Throwable, whereas most user-errors and other recoverable errors would extend Exception, which itself also extends Throwable. This distinction between Error and Exception would allow for PHP to internally throw errors, which usually are not caught (as it would mean catching all Throwables).
This would allow for current things to work as usual, as most people wouldn't catch Errors. -
Emilio, case in point, if usage of empty() without a variable parameter causes a parse error then it means that empty() is a special case within the parser, which is terrible. empty() should be no different from every other function in the PHP standard library.
posted on Feb 21, 2009 at 11:30am | context -
You're right, it is cool. One dislike about php I have that I mentioned is that there is no actual way to reference or return a function. call_user_func is roughly equivalent to doing: $func = 'a'; $func('hello world'); As shown, $func is unfortunately not a reference to the function "a" itself but rather is a string representation of it. When you say passes a function by reference, do you mean in object context when passing array($this, 'func_name') as the first parameter?
posted on Dec 28, 2008 at 4:43pm | context -
I'm not (primarily) a Java developer... I started with PHP, and have focused most of my learning on it.
posted on Dec 28, 2008 at 4:40pm | context -
Great advice.
posted on Dec 28, 2008 at 4:07pm | context -
The main idea of the yield control except (since renamed to MetaResponse) is to change the resource entirely--as though a new response is being made. With that in mind, it made sense to let it bubble up entirely in order to properly escape the current response and then change the application to a new one.
posted on Nov 19, 2008 at 12:40pm | context
To that end, a 404 or 500 is really just a different response sent to the server. 404 and other http-related errors don't make sense as normal exception, i.e. there is no way to 'handle' a 404 if it is caught other than to display something. With this in mind, the meta response for errors is really just the second step, e.g:
either an error occured and an exception was caught, then we throw a 500 meta response if we can't handle it, or if we know there's nothing we can do to recover from the error we can throw a 500 meta response right away. It's purpose isn't to solve any problems, merely change the response. -
Lewis: Because the process of separating the returned columns can be expensive, I add the following into the query so I can quickly identify if a PQL was in fact compiled with PQL:
posted on Aug 21, 2008 at 9:31am | context
SELECT 1 AS __pql__, 1 AS __first_table, .. prefixed cols ..., 1 AS __second_table, ... prefixed calls, etc.
Then I can do a simple isset($row['__pql__']) -
Thanks for that. It is among many other things (the way packages are structured, needless complexity in the db package, etc) I need to think over.
posted on Aug 6, 2008 at 10:34pm | context -
Oh neat, I was thinking of doing something similar (because python has it too) but I was more thinking of evaluating the tests within a function itself. I realized it might not be the best idea (because my approach would lead to an infinite loop), and I had already written some of the code to move the *'s and such from the doc block so I just went from there.
posted on Jul 2, 2008 at 10:23am | context -
Yes, sorry, I manually moderate comments (as well as let akismet do some work).
posted on Jun 20, 2008 at 11:36pm | context -
Thanks! I wouldn't have spotted that. It's now been fixed in subversion. I think it's clear that subconsciously I want to be in space ;)
posted on Jun 15, 2008 at 12:41pm | context -
The length of the code is a concern of mine. For the basic model building I find it's quite compact, but for queries it still takes a lot to do certain things. Here is my reasoning behind it thus far, aside from it being fun:
- Queries are unambiguous.
- You can focus more on what you want to get at rather than how you want to get there.
- The language is portable to other domains (as I mentioned, my intention is to make it work for XML).
- As you might have found on my blog, I developed an ORM last year, and although I am very happy with it, it does have its flaws. For some things you just want to write a query because it can be ugly fitting it into the model, and with my previous system, one needed to get a record of something from the database in order to access what that model was related to, instead of being able to do all the relations right from the start. So, first, I wanted an SQL-like syntax that is entirely divorced from the database. Second, I wanted it to be restricted to the common uses, such that switching to actual SQL is easy.
- I wanted to make an ORM entirely divorced from the database.
- Figuring out the join order isn't cheap. I need to create a dependency graph and then recursively build joins out of it. (this only happens in the compile() function call). That means at some point for it to be decent, I would need to be able to precompile queries (to sql) and store them somewhere. Segue: One thing I was thinking, though, is that for compilation, one would need to provide a unique identifier for a query. This same identifier could be seamlessly used with something like memcached as well.
-
An interesting thing I've dreamed of is that PHP would make variables names not require the $. That is, both variable names and function names would be recognized in the same symbol table, thus allowing for the easy mixing of functions and variables that you will notice in languages such as Javascript that consider functions as first-class entities. To do this, it would seem that the PHP team would only have to make variables not require the $ as a prefix to their name, and simply add the $ to the allowed characters of a symbol. Technically nothing, in terms of symbol overlap, would happen error-wise, so this could be a fun change. But, I also don't expect them to do this, which is unfortunate.
posted on Apr 21, 2008 at 10:48pm | context -
Closures are both a convenience and an extremely powerful tool. Generally in PHP, there is the unfortunate mindset that everything that can be done with a closure can simply be done with a predefined function and then we can just pass the name of that function around. A common example of this would be any PHP function that accepts a callback: it takes the string name of a function and then applies it to something. In the most basic sense, we could instead create a function on-the-fly and pass it to that original function; however, clearly this doesn't add much value to closures. Instead, lets consider closures and their scope. In Javascript, if I define a variable outside of the function, then that function can access that variable. I can keep nesting functions and that (global) variable will still be accessible to the innermost depths. PHP, on the other hand, has a different way of handling globals. Best practice has global variables as being explicit, i.e. you need to use $GLOBALS or the "global" keyword. In its current state, we can observe that PHP's global keyword seems to look up to the parent scope, for example: $var = 123; function foo() { global $var; // $var is now accessible from within foo() } If this tradition were continued and anonymous functions were introduced, then a bit of annoying trampolining, as it were, would need to be done to have the same effect: $var = 123; function foo() { global $var; $anon = function() { global $var; // yay! $var is accessible. } } And so we see that in making use of one of trying to propagate variables down into lower lexical closures, we go against best practices, i.e. not to use global variables, and end up with some messy code. Clearly, in its current state, closures won't yield the nice benefit of scoped variables that we've come to expect from Javascript. So, what can we still rely on? First, lets look at the current state of PHP functions: function foo() { function bar() { // ... } } This is legal PHP, but it doesn't have the effect one might expect. Instead of bar() being local to foo, and only existing within foo, when foo is called bar becomes a globally accessible function. In this sense, PHP has failed to encapsulate bar within foo. One would expect this to change with the introduction of lexical closures. Thus far I've really made no argument for lexical closures/anonymous functions in PHP besides a minor fix to the way it encapsulates functions. Given this, WHY do I think adding closures to PHP is a good idea? In general, I think it would represent a shift in mindset and workings of PHP. Adding closures would require internal changes to how PHP works, unless closures just end up being syntactic sugar for create_function. The changes I'm talking about would mean that PHP would need to start recognizing functions in an entirely different way--that is, they would be first class, scoping would work in the way one would expect it to work in a language like javascript, etc. Almost all of this represents a dream for a better PHP, and most of it isn't even practical given how PHP works. And so, I will answer the first question by stating that closures would help PHP insofar as they would require it to get out of the hole that it's dug with create_function, using strings to call functions, and other such hacks. To answer your other question, about when closures would be nice to have and applicable to real-world coding is much simpler than you think. Given that PHP has only one namespace (this changes in newer versions), we obviously cannot have one function named the same as another. Also, with many algorithms, especially ones that are most easily understood with recursion, we often need more than one function to perform the operations, and thus we end up having to create our basic function, then a few other functions with a prefix of some sort or a way to identify them. Obviously, we could go the Java way and put all these multistep algorithms into a class, but I've always found that ugly. Consider quicksort and mergesort. PHP already provides these built-in, but whatever. Both these algorithms have distinct divide and conquer steps. It would be especially convenient, and very understandable if one could only do: function quicksort(..) { function divide(...) { } function conquer(...) { } ... } function mergesort(..) { function divide(...) { } function conquer(...) { } ... } Neither of these algorithms requires the abstraction of a class, but both of them benefit from the encapsulation of closures. Within (and only within) each main function, the closures are defined and are very obviously linked to the parent functions without the need to create all global functions with prefixes. I don't feel that the above answer will convince everyone, as prefixes or different function names, etc, are simply the accepted way of doing things. I do, however, feel that closures provide the programmer with a different (and I think better) way of approaching problems--which is to give the programmer the ability to work on subproblems and not have to deal with any annoying name conflicts. I also think that the changes that closures would require of PHP would be beneficial in general. So, regardless of if this has convinced you, or just exposed some of the inherent limitations of PHP's current setup, I think it's in your best interest to explore other languages (such as Javascript, Python, Ruby, etc) that support closures and get a feel for how it changes your workflow and your approach to problems. As side note, with closures, one might also expect partial application and proper currying ability, which would just be *sweet*.
posted on Apr 21, 2008 at 10:41pm | context -
Normally I do that. In fact this has no real benefit as it's simple to manipulate the level and propagate changes up the tree. The mptt implementation didn't include a level field and so I thought it would be fun to see how it could be implemented iteratively with php.
posted on Mar 3, 2008 at 5:42pm | context -
In terms of practicality, this use of Reflection is an edge case; however, I still felt it cool to show that "yes it can be done."
posted on Dec 14, 2007 at 1:52pm | context -
Your right about that for the case where you know the arguments that you want to pass to the constructor. What I wanted to show with the Reflection example is that we dynamically construct any class given its name and an *array* holding its arguments. If, for example, instead of statically knowing the arguments 'hello' and 'sir', you had $args = array('hello', 'sir'), how would you propose that be done? ;)
posted on Dec 14, 2007 at 1:50pm | context -
Quinton, Good point, extract can be very dangerous. Usually I would do it on a known associative array and pass it to an enclosed scope (in the case of a template engine). In the case of templating, extracting request variables would be somewhat redundant and one would expect that the extract would be performed from within in a function whose role it is to solely deal with templates and nothing else. As long as the templates are separated from the code by using that function as a proxy then the default scope will be unaffected.
posted on Aug 30, 2007 at 7:32am | context -
You're right that error recovery should not be the responisibility of exceptions. Exceptions are essentailly a way of triggering and then handling triggered predictable errors and their responsibilities should not extend to modifying the state of the code that they are reporting. Unfortunately PHP does not have a finally or else clause for exceptions and therefore if an exception is triggered there is no way to clean up after it if it's not caught! The above hack breaks the rules so to speak in order to allow the missing functionality.
posted on Aug 25, 2007 at 8:13pm | context -
Mike, Unfortunately php is not like java/cf in that state can persist across multiple requests. Although porting frameworks is nice, given that you are experiencing a huge loss in performance, I think that it's worth changing your strategy. Aaron, You're right, the example is rather lame. I couldn't think of anything off the bat that would demonstrate the power of the reflection api without too much code. That call user class came to mind as it is something that at times I (and I suspect others) have wanted but could not do. Otherwise, the hint of how reflection could be used for such things as dependency injection was meant to fill the gap for more experienced programmers who--understanding introspection--could imagine how it would be done without needing written code.
posted on Aug 24, 2007 at 12:54pm | context -
Hey, Sorry for the late comment, I've been extremely busy... David, in php5 case does not matter; however, iirc in php5 it does.
posted on Aug 24, 2007 at 12:49pm | context -
JBW, in that case I suggest you take a look at my most recent post: 12 things you should dislike about php. Otherwise in many respects I agree with you; there's a reason why my new favorite language is python ;)
posted on Aug 20, 2007 at 2:50pm | context -
http://ioreader.com/code/reflection.phps
posted on Aug 20, 2007 at 9:20am | context -
Mike, using magic functions to pass attributes to a class only affect attributes that the class doesn't already own. Implementing arrayaccess does not mean that attributes can't be accessed in the normal way and it also does not mean that you can't use the magic functions. The beauty of the magic functions and arrayaccess is that they are not mutually exclusive. You can use both at the same time and you can implement them in different ways if you so choose. The subject of storing an object persistently is much trickier. var_export() is nice for arrays, and serialize can be bulky. For storing objects, I would suggest having the class implement Serializable and serializing them (unfortunately). However, that doesn't have to be the end-all-be-all of the problem. Can you describe what the nature of the data you want to store is, and are you storing it to transfer state between requests?
posted on Aug 19, 2007 at 6:56pm | context -
Zelborg, you're right, that would clean it up a bit! Generally my practice for doing that if statement is that I will normally put some sort of logic in there. Eg, lets say I want to cache an array. Initializing the static variable to an empty array would work off the bat, but then the cache wouldn't work as expected. How would I know if I've already fetched the information or not? Do I check if that array is empty? What if the initializing code returns an empty array? For the simple examples (such as the above one) you're bang on about simplifying that function; however, as the static keyword is used for more appropriate things it's generally extremely useful to tell the difference between uninitialized (eg: NULL) and initialized (eg: an array, empty or not).
posted on Aug 19, 2007 at 9:25am | context -
James, thanks, the example would have been incorrect had you not pointed that out :)
posted on Aug 19, 2007 at 9:20am | context -
Rodey, in one thing you are right: this was a reactionary response. I was disappointed with the previous post mainly because it didn't touch on a lot of the more advanced concepts and what is interesting about them. Given some of the comments on this article here and over at Digg it's clear to me that the other post was well suited towards a different subset of PHPers. That being said, I don't see why this post can't compliment the other one (despite my initial intention).
posted on Aug 19, 2007 at 12:01am | context -
Rodey, I can see how my generally long posts could be dry to some people :) I actually wrote this article twice, the first time was rushed, poorly written, and lacked a lot of the meat of what's there now. I decided to rewrite and make it longer because I didn't think it was enough to simply say: "this is interesting, figure out for yourself why." Some functions are immediately obvious, but the practical applications of others are not. For example, preg_split is a function I often use. Besides being a superior explode(), I also use it for html, bbcode, rss, and template parsing. Further, the SPL is full of amazing classes and interfaces but some of them are advanced concepts. For people new to iterators its not completely obvious how they can be applied to an every day use. It's understandable that some people will find this post boring; however, I can't imagine someone understanding what I see in this list without the context I have given.
posted on Aug 18, 2007 at 11:33pm | context -
Tarique Sani, thanks for the tip! I have never actually used that function but a quick look in the manual shows me its usefulness. I have added into my article :)
posted on Aug 18, 2007 at 10:39pm | context -
Chris, thanks for the tip. There is now a RSS feed link in the head and I also put the post name into the title (dunno why I forgot that earlier).
posted on Aug 18, 2007 at 10:15pm | context -
As a side note, one of the things I dislike most with PHP is that functions are not objects and thus cannot be self-calling. The above hack using create_function semi solved the self-calling issue.
posted on Aug 18, 2007 at 12:19pm | context -
In most ways you are right, this is not practical, it does not solve a problem, and it's generally quite an ugly solution. However, the goal of this was to look at php's limitations as a challenge and try to come up with a proof-of-concept way to call lambda-like functions at their creation instead of after their assignment. In this respect, I succeeded. I disagree with you that this code isn't insightful. As I've mentioned, this does not solve any realistic problems in PHP, and with respect to solving problems it is lacking insight. However, experimentation is healthy and I think that this was an insightful solution to the problem (or rather, a challenge to myself) of calling a created function on the spot.
posted on Aug 18, 2007 at 12:14pm | context -
The difference is that the betteraccess (I call it just an overloard class now) class implements ArrayAccess and so can also be accessed as if it were an array. With your code, I would only be able to do this:
$foo = new Foo; $foo->bar = 'hello'; echo $foo->bar;
One of the first major differences is that I don't define a Foo::$vars array to hold any data so the class itself has no functionality. That is why it is abstract. The point of it was to make it so that any class that extends it only needs to make the four overload functions that you have used and implement them in whatever way they wish. Once they've implemented the overload functions, as you have, then they can now access the class as if it were an array or an object. So, for example, if I changed your code a bit..class Foo extends BetterAccess { // ... } $foo = new Foo; $foo->bar = 'hi'; // both are equivalent echo $foo->bar; echo $foo['bar'];posted on Jul 18, 2007 at 9:01am | context -
One thing I've found this type of technique particularly useful for is that if you are mixing PHP in with HTML and need a simple way to select an option in a select menu / radio button, you can build a create_function on the spot with the value of what should be selected in it that will return either nothing or selected="selected" or checked="checked" depending on what input it gets.
posted on Jul 12, 2007 at 10:01pm | context -
Well, for all the things I don't like about wordpress, there are a lot of things I do, for example: it has a great administration panel, it automatically deals with ping back and sending out pings, it supports tons of plugins (although with a new front end they won't be that useful) and it supports tons of themes (same thing). On the whole, wordpress is an amazing product, I just don't think its developers are that amazing.
posted on Jul 6, 2007 at 8:57am | context -
Mainly from geoffrey's old php4 framework, with a few additions such as a slightly different relations system than he used.
posted on Jul 5, 2007 at 10:12am | context -
Hehe, yes, right now I am just re-creating the wordpress front end using my framework. When I'm done it should generally be okay to use.
posted on Jul 5, 2007 at 8:31am | context -
Thasmo!!!!! Yes, I am not that fond of CodeIgniter either; however, I need to use it for work so I tried to make the best of things ;)
posted on Jul 4, 2007 at 8:59am | context -
Watch out tho! The installation instructions don't necessarily hold valid any more because I'm constantly changing parts of the framework :P
posted on Jun 28, 2007 at 8:31am | context -
Yes, once the whole thing has generally been debugged and I've added a few more necessary features then I will create full documentation on how to use it :)
posted on Jun 26, 2007 at 11:28pm | context -
Great! Okay, let me explain how to get it up and running. What you will be downloading is my php5 framework in development. The uploader is part of that! first, go download/unzip http://ioreader.com/code/iocore.zip second, put it somewhere accessible by either your own local server or online. I suggest putting the 'valkyrie' folder above the document root, where the 'wwwroot' directory is the document root. Whatever. Assuming you are up and running, go to your equivalent of: http://localhost/iocore/wwwroot/upload/install/ to install it, then go to http://localhost/iocore/wwwroot/upload/ and you should see it! To configure which FTP server it connects to, check out valkyrie/application/config.php. One problem I've been having recently is that it copies the files over but not their contents. If you get any other php errors, please tell me! You find the model layer a bit of a mess if you delve into it because it's what I've recently been working on. Also, the only database table used in the uploader is /valkyrie/application/models/log.php. The uploader, by default, uses a SQLite database.
posted on Jun 21, 2007 at 10:26pm | context -
I have started working on a jquery script to do the same thing that i do in this script for dragging and dropping multiple objects at a time. I'll post the code on this blog when I'm done. Otherwise, if you're interested in the code, I could post a zip online.
posted on Jun 20, 2007 at 8:45am | context -
i) It only requires CAPTCHA validation once.. if there's a bug in that process then go look in the thread controller. ii) yes I have had that bug but not for a *really* long time.. I thought I solved it a while ago. Guess not. iii) Go into /k4bb/bbparser.php to see.
posted on Mar 15, 2007 at 8:05pm | context -
Yeah that sounds good.
posted on Mar 15, 2007 at 3:32pm | context -
Not complete. Most of the admin panel is missing, most of the rest is done. :P
posted on Mar 15, 2007 at 1:29pm | context -
If you're viewing a single/multiple tags at once, on the right side of the page there will be other tags listed that are often used with that tag. Beside each tag name there is a little icon, click it. If you look at the url you will find you are now at /tags/tag1+tag2/. You can select as many tags as you want. Now, beside the main header "Tags: tag1, tag2" there will be a small 'save' button. Click that! Hope this helps.
posted on Mar 14, 2007 at 9:53pm | context -
To modify the permissions, go to: /admin/permissions/ There are 3 pages of permission management: roles, objects, and a combination of the two. I think you will like the way permissions work in 1l, its kind of a fake-ACL setup. If you want a more in-depth description, just ask or check out the controllers that work with them.
posted on Mar 14, 2007 at 8:37am | context -
So I just did yet another tiny update, and everything is still working for me :P Do you have 1l running on any site so I can debug through that?
posted on Mar 13, 2007 at 10:54pm | context -
Lee, I don't even know if I made that admin password do anything.. I think I made it so that I would eventually implement it but didn't do anything past that.. LOL. I'll try to fix all that stuff later tonight, I'm off to calc class then I'll be doing econ / sociology for the rest of the day/night.
posted on Mar 13, 2007 at 12:06pm | context -
Mainly I meant the captcha and another problem I was having. In solving the other problem, the captcha started working. The I realized that the captcha never stopped working, it was simpy that the path to the captcha image was incorrect... The captcha is fixed on your end though, right?
posted on Mar 13, 2007 at 12:35am | context -
Lee, I've updated the SVN with two changes I just made. The files I changed were the .htaccess and k4bb.php. These changes should solve all of the problems :D
posted on Mar 12, 2007 at 11:28pm | context -
Susan, Sorry! I still haven't fixed the CAPTCHA script.. I'm not entirely sure what's wrong but then again I haven't really dedicated any time to fixing it (been busy, lazy, etc). So, that's why users cannot register. The queries displayed at the bottom are a debugging mechanism, to hide them, go into: upload/include/app/filters/debug_post_filter.php and just comment out everything within the filter's execute function (or remove it, whatever). Unfortunately there is no actual installer becuase this is unfinished software! Otherwise, here is the best place to get help.
posted on Mar 12, 2007 at 3:14pm | context -
I think when I wrote this jquery didn't have as nice source code.. that was my excuse :P Yeah, I stay away from spaghetti code now :D
posted on Feb 26, 2007 at 5:01pm | context -
Whoops, sorry about not including some of the arguably *key* files. lol. I don't know why they weren't added to the repository when I committed everything.
posted on Feb 18, 2007 at 1:36pm | context -
Thanks!
posted on Feb 4, 2007 at 10:40pm | context -
The IE team did create the XMLHTTP ActiveX control; however, what I was talking about was the actual XMLHttpRequest object, which most other browsers support. IE7 now has it, even though it still links to activex.
posted on Feb 4, 2007 at 1:01pm | context -
You're right, graceful degredation is a must. I think my main pet peeve is that AJAX is such a simple thing to implement and there are too many people doing it in stupid ways. In fact, a lot of the time it is used for the sake of having it.
posted on Jan 31, 2007 at 4:25pm | context -
I can put up a zip, although I really don't suggest anyone using it. It's good but the heirarchical system needs to be remade.
posted on Jan 18, 2007 at 11:03pm | context -
It's just an optional way to be able to stop other observers from executing.
posted on Dec 22, 2006 at 9:22am | context -
Damnit.. now I need to change it. I will change it once I'm done my exams (in 2 days)
posted on Dec 17, 2006 at 12:30pm | context -
Yeah I could do that too, was just putting v1 up for old memories :D
posted on Dec 16, 2006 at 10:21am | context -
You'll find out soon enough :D
posted on Nov 26, 2006 at 11:41am | context -
The goal is to be done by christmas.. but it's definetely not what anyone thinks it is an it doesn't have a practical use for most people, but it will be cool!
posted on Nov 23, 2006 at 12:07pm | context -
Stupid wordpress fooked up the code a bit.
posted on Oct 23, 2006 at 7:48pm | context -
Make sure to take the second version, http://www.flyingwithfire.com/2006/08/29/jquery-inspired-actionscript-library-part-2/ It works the same, but less code and more functionality. I have yet to add the effects part in though.
posted on Sep 22, 2006 at 11:00am | context -
The last bunch about public static members and singletons might sound a bit odd, so if it didn't come accross as making any sense to anyone, I got my main inspiration from: http://www.bitchwhocodes.com/archives/2006/04/singleton_vs_st.html. Sge has done a much better job explaining it.
posted on Aug 28, 2006 at 1:54pm | context
