"Stephen R. van den Berg" srb@cuci.nl wrote:
Well, actually, since I never read this formally (objects should start with uppercase), I didn't realise that this was/is the convention in Pike. They actually are objects, so I'll rename things to: USB.Devices(), USB.Iterator(), USB.Device() and USB.Transfer() instead.
What is ever "read formally" in Pike? ;) The general sentiment is that ObjectsAndModulesAreSillyCapsed, function_names_use_c_style_underscores, and CONSTANTS_ARE_ALLCAPS. That is the most prevalent style in the existing modules. Although - this being Pike - there are of course plenty of exceptions, in particular in the older modules like Sql (at one point Sql.sql changed name to Sql.Sql to adhere better to this convention, but it was a bit half-baked since most other objects in there didn't follow along).
USB() which simply is USB.Devices() moved up a notch. I.e. delete USB.Devices() and simply create just USB() which does everything the original USB.Devices() did.
So then USB.pmod would become USB.pike, if you'd written it as a pike module? Very well, but the risk is then that you have nowhere to put static utilities, i.e. various functions that aren't bound to any specific object. You may not have any such things now, but in the future you might want to add something like that, and then you'll have a problem. I'd be very wary about spoiling that possibility by design.
The risk is then that static functions go into one object or another, where they become unnecessarily hard to reach. One example of that is Sql.mysql.quote. It's not db connection specific, and I have on several occasions wanted to use it without a connection, to format sql snippets for later use and so on. I've then been forced to do various workarounds because of that. It should have been on a static module level, which should be resolved through the same generic mechanism that Sql.Sql uses to resolve the db connection objects.
Then the USB.Iterator() and USB.Device() and USB.Transfer() are simply classes *inside* the USB() class, which eliminates the need to carry an explicit reference from those back to the old USB.Devices(), since they are children of the USB() class, they can reference it implicitly.
Those implicit references are at the bottom explicit parent pointers in the object storage. They are optional - the pike compiler only generates them if there are references into the parent scope, and in a cmod you'd have to specify PROGRAM_USES_PARENT to get them. So you can just as well have your own pointers in your C code and achieve the same thing even if the classes are siblings.
If there are no obvious objections, what would be the easiest way to implement this? Is this doable in the cmod?
A C module is always a singleton object on the top level, so you'd have to hide it (typically with a "_" prefix) and publish an object which is made available through a small USB.pike module that inherits the hidden implementation.
- The distinction between what is a module and what is a class should be irrelevant; someone looking at the language simply sees (nested) classes. The fact that a "module" actually is sort of an empty class which cannot be instantiated by itself seems irrelevant (one could even say confusing).
On the contrary, the concept of modules, and what makes them different from classes, is helpful for users to understand. They are a) singletons in the pike process, and b) got a lifespan which is just as long as the process itself. This makes them the pike correspondence to the static storage class in many other languages. That has proven to be very useful as a programming paradigm, so it should be exposed. It's rather the fact that most modules really are classes that can be considered a technical detail that users shouldn't have to worry themselves with, at least not to begin with.