I now have a cmod which is in a subdir src/post_modules/USB, which gives me an USB.devices(), USB.Iterator(), USB.device() and USB.transfer().
The usual way this works, is that one starts with:
object dev=USB.devices();
and then you do a foreach() which gets the Iterator, which delivers the devices, etc.
Now, what if I'd like it to start with:
object dev=USB();
(and then the rest with foreach() etc. same as above).
Are there any aesthetical or technical reasons not to prefer this? (I'm all for brevity). If there are no obvious objections, what would be the easiest way to implement this? Is this doable in the cmod? Are there any existing modules that did it this way?
"Stephen R. van den Berg" srb@cuci.nl wrote:
I now have a cmod which is in a subdir src/post_modules/USB, which gives me an USB.devices(), USB.Iterator(), USB.device() and USB.transfer().
I take it that neither USB.devices nor USB.device are objects, since they start with lowercase. What are the names of the objects that represent them?
Now, what if I'd like it to start with:
object dev=USB();
(and then the rest with foreach() etc. same as above).
Are there any aesthetical or technical reasons not to prefer this?
Well, I have a designwise reason: It's confusing. USB is the module, but what you get there is some object inside the module. Using `() directly on the module makes it appear to be an object, but the object and the module are really two different things, and it's less confusing if they are kept separate, and that the separation remains clear.
If there are no obvious objections, what would be the easiest way to implement this? Is this doable in the cmod?
It should be simple to do with an `(), even in a cmod afaik.
Are there any existing modules that did it this way?
There is an experiment in lib/modules/Threads.pmod which tries to unify the Thread module with the Thread.Thread objects. There you can see some effects of trying to do that, and I've also left a fairly lengthy critical comment on why it's not such a great idea.
I'm not implying that's what you're trying to do here, though - from the looks of it you may be aiming only at a simple shortcut. But even so my argument earlier remains applicable.
Martin Stjernholm wrote:
"Stephen R. van den Berg" srb@cuci.nl wrote:
I now have a cmod which is in a subdir src/post_modules/USB, which gives me an USB.devices(), USB.Iterator(), USB.device() and USB.transfer().
I take it that neither USB.devices nor USB.device are objects, since they start with lowercase. What are the names of the objects that represent them?
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.
Now, what if I'd like it to start with: object dev=USB(); (and then the rest with foreach() etc. same as above).
Are there any aesthetical or technical reasons not to prefer this?
Well, I have a designwise reason: It's confusing. USB is the module, but what you get there is some object inside the module. Using `() directly on the module makes it appear to be an object, but the object and the module are really two different things, and it's less confusing if they are kept separate, and that the separation remains clear.
Well, not quite. What I am doing now is something like this:
object dev=USB.Devices();
From this follows an USB.Iterator() object implicitly in foreach, then
an USB.Device() object which carries a reference to the original USB.Devices() it sprung from, and ultimately a USB.Transfer() object which carries a reference to the USB.Device() it originated from.
What I'm thinking is that I create the following hierarchy of objects:
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. 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.
If there are no obvious objections, what would be the easiest way to implement this? Is this doable in the cmod?
It should be simple to do with an `(), even in a cmod afaik.
Erm, yes, this would be the shortcut method. Visually, it's the same effect as what I really wanted to do.
Are there any existing modules that did it this way?
There is an experiment in lib/modules/Threads.pmod which tries to unify the Thread module with the Thread.Thread objects. There you can see some effects of trying to do that, and I've also left a fairly lengthy critical comment on why it's not such a great idea.
I'm not implying that's what you're trying to do here, though - from the looks of it you may be aiming only at a simple shortcut. But even so my argument earlier remains applicable.
As to the matter of being confusing...
From a standpoint of someone looking at the language from the outside
(forgetting the implementation details for a moment), I see the following:
- Pike is an object oriented language. - There seems to be an implicit unnamed master class which contains a method called main() which is started by the operating system. - All variables, functions and classes one defines are actually variables, methods and classes which are part of this implicit unnamed master class. - Whenever a variable, function or class is not found to be part of this implicit master class, it is searched for in the libraries. - This means that USB() could be either: a. A function/method defined in the running program's implicit master class. b. A system function. c. A class defined in the/some library. - This means that USB.Devices() would simply be a class Devices() declared inside a parent class USB(). - 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). They both seem to be classes, they live in the same namespace. Which (to me) would mean that the language can be explained without ever mentioning the word module, and without changing semantics.
"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.
Martin Stjernholm wrote:
"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
Well, the rest was already in my DNA (well, except the IMHO overuse of underscores, but that's what conventions are for, of course, to adhere to even if you don't quite like them).
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
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
Ok, fair enough. Didn't think of this application. I'll stick with USB.Devices() then, and drop the USB() idea.
- 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.
Useful reasoning. Somehow this should translate into improved explanation about what a module is and what a class is in the Pike documentation (or maybe I didn't read this part of the docs carefully enough, and it's just me that missed part of these points in the past).
pike-devel@lists.lysator.liu.se