www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Function APIs and/or classes

reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Walter and I are having a little friendly disagreement which is holding up the
inclusion of the std.loader module into Phobos.

Basically, it goes like this:

Walter believes that every module should have a single, unambiguous API. He is
happy for that to be either free functions, or classes, although he would
probably admit to a preference for classes for most things.

I believe that what Walter believes is a good thing, except for the fact that I
see that it limits the choices of developers. Some people want to use free
functions, others a class-based approach, others to mix and match as they deem
appropriate. (I'm in the last camp.)

I don't ascribe to the free function-only approach because object-orientation
has
a lot going for it. If people want that exclusively, then C is the language for
them, methinks.

I don't ascribe to the class-only model for the converse reasons - i.e.
sometimes
free functions are more convenient/appropriate - in general, and for the
specific
reason that I don't believe that exceptions represent the "one true
error-handling mechanism", and I don't want to be forced to use them when _I_
deem that it's not appropriate to my requirements. Sometimes I want to write
small utilities and simply get a success/rail result from a function. I
certainly
want this facility with std.loader, as I plan to write version/COM-server
trawling utilities and I don't see it as appropriate to be using exceptions
(since exceptions are for exceptional circumstances, not for testing things, IMO
at least).

Hence, the way I've written loader.d (and some other modules), is that there is
a
free function API, and a thin class (+ exceptions) wrapper over that API. This
affords the flexibility to suit all tastes.

I won't bang on about the advantages of this approach further, as those that
agree already agree, and it's my experience that those who want only a
class-only
approach cannot be persuaded to look at the virtues of the other side. (Walter
asserts that the dual approach makes the code harder to maintain. I assert the
contrary. After much debate, we're both still seeing it our own way. Must be one
of those things, I guess ...)

What I'm interested in is getting a feeling for the general level of support for
the following options.

Before I enumerate those options, let me make it clear that I don't believe this
approach is valid for all modules, far from it. The std.windows.registry,
std.mmfile and the std.perf (not yet included) modules are entirely class-based.
The std.recls module has both, and I have written std.loader as both. It is this
latter that is the sticking point, as Walter does not want to release it in such
a guise.

 The options as I see it are:

1. free functions only
2. class-interface only
3. combined approach, in same module
4. combined approach, in (for example) std.c.loader.d (for the free functions)
and std.loader.d (for the class)
5. Some other combined approach that I've not anticipated. Please suggest

Please let me know your thoughts

Cheers

Matthew
May 07 2004
next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Matthew wrote:

3. combined approach, in same module
  
We're only hearing one side of the story but 3 is the obvious choice for me. Some times it nicer to deal with classes others, free-functions. You've gotta strike the right balance. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
prev sibling next sibling parent reply Ant <Ant_member pathlink.com> writes:
In article <c7fhhj$2gtc$1 digitaldaemon.com>, Matthew says...

Please let me know your thoughts
I'm pissed off now! Please state clearly if our analises and conclusins are going to by included on a product that is the sole property of Synesis before asking for contributions. What Synesis decides to do with that product is irrelevant for the fact the our work might be beeing donated to Synesis. Thanks. Respectifully (how ever it's spelled) Ant
May 07 2004
next sibling parent reply Derek <ddparnell bigpond.com> writes:
On Fri, 7 May 2004 09:19:35 +0000 (UTC), Ant wrote:

 In article <c7fhhj$2gtc$1 digitaldaemon.com>, Matthew says...

 
Please let me know your thoughts
I'm pissed off now! Please state clearly if our analises and conclusins are going to by included on a product that is the sole property of Synesis before asking for contributions. What Synesis decides to do with that product is irrelevant for the fact the our work might be beeing donated to Synesis. Thanks. Respectifully (how ever it's spelled)
<soapbox> There is a distinction between a software specification and the implementation of that specification. It is (mostly) reasonable that the sponsor of an implementation (not necessarily its author) have ownership of the implementation. However, any original ideas that are contained in a specification, are always owned by the author of the idea until ownership is explicitly assigned away by the author. Thus I feel that discussions like these go in to maintaining the specification. It then up to the implementation team to convert the changes into real code. To summarize, Synesis will continue to own the Digital Mars D compiler code but our original ideas that are incorporated into the D specification are not automatically owned by Synesis. You are quite free to write your own D compiler and thus own that implementation. </soapbox> -- Derek Melbourne, Australia
May 07 2004
parent Ant <Ant_member pathlink.com> writes:
In article <ki1h4w8lihf7.7epxl2sd0ogo.dlg 40tude.net>, Derek says...
<soapbox>
You're right. and Seems nobody cares. Probably is not as important as I thought. Ant
May 07 2004
prev sibling parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Ant wrote:

 What Synesis decides to do with that product is irrelevant for the
 fact the our work might be beeing donated to Synesis.
Ant, I'm sorry, but why do yuo really care that much? Do you feel that your suggestions in this area are worth - what, $50, $100 dollars? So you're donating them to Synesis. Pah... this is a problem because? It's not like anyone's going to claim your suggestions were not written by you. It's not like anyone's going to sell your suggestions. It's not even like anyone is going to horde them. If you don't want to offer your opinions or suggestions, hey - that's your call. But blaming it on a license seems a bit wishy washy, because really what does it matter who owns your comment? If it were even that my comment would suddenly be owned by Synesis, I would still comment. If I thought I could give a comment to Microsoft that would improve things in a way, even if they would own my comment... I'd do it. Who cares who owns it? I mean, I'm a capitalist too, and I can and have sold just my opinion before, but this is really a bit much, isn't it? -[Unknown]
May 07 2004
parent reply Mike Wynn <one_mad_alien hotmail.com> writes:
On Fri, 07 May 2004 11:42:08 -0700, "Unknown W. Brackets"
<unknown at.simplemachines.dot.org> wrote:

Ant wrote:

 What Synesis decides to do with that product is irrelevant for the
 fact the our work might be beeing donated to Synesis.
Ant, I'm sorry, but why do yuo really care that much? Do you feel that your suggestions in this area are worth - what, $50, $100 dollars? So you're donating them to Synesis. Pah... this is a problem because?
its not a problem its a principle.
It's not like anyone's going to claim your suggestions were not written 
by you.  It's not like anyone's going to sell your suggestions.  It's 
not even like anyone is going to horde them.
it is exactly that, we all accept (I assume) that D is owned by Walter/Digital mars, and any money Walter makes from our sugestions is just payment for giving us the D compiler for free. however with Synesis it is not so clear, why loader.d for instance, instead of improving the dynloader.d I posted feb 2003 http://www.digitalmars.com/drn-bin/wwwnews?D/11102 which was free for everyone to use and modify and give back to the community without charge or restriction, Walter/synesis chose to give similar functionality but with restriction.
If you don't want to offer your opinions or suggestions, hey - that's 
your call.  But blaming it on a license seems a bit wishy washy, because 
really what does it matter who owns your comment?
I think he's very justified in blaming the license, he's put in a lot of effort for little/no reward only to find that someone (other than Walter) may be rewarded for his efforts.
If it were even that my comment would suddenly be owned by Synesis, I 
would still comment.  If I thought I could give a comment to Microsoft 
that would improve things in a way, even if they would own my comment... 
I'd do it.  Who cares who owns it?  I mean, I'm a capitalist too, and I 
can and have sold just my opinion before, but this is really a bit much, 
isn't it?

-[Unknown]
that is you opinion, and your choice, do not expect everyone to wish to follow your example, which is uncorroborated. Mike
May 07 2004
next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Mike Wynn" <one_mad_alien hotmail.com> wrote in message
news:fmon90dcch9sqi36uqnv33q6vj8s7hf5i7 4ax.com...
 Walter/Digital mars, and any money Walter makes from our sugestions is
 just payment for giving us the D compiler for free.
I haven't made any money whatsoever off of D itself <g>. The idea is to make money doing presentations on D and producing books, articles, training materials, etc.
 however with Synesis it is not so clear, why loader.d for instance,
 instead of improving the dynloader.d I posted feb 2003
 http://www.digitalmars.com/drn-bin/wwwnews?D/11102
 which was free for everyone to use and modify and give back to the
 community without charge or restriction, Walter/synesis chose to give
 similar functionality but with restriction.
Matthew has promised to change the license, but it's moot at the moment because we don't agree on the design of loader.d. Be that as it may, there is an ongoing problem here of people posting code like yours - it gets lost in the blizzard of postings. We must do better. I propose one of the two: 1) make a newsgroup digitalmars.D.sourcecode for contributions. 2) add it to the D wiki.
May 07 2004
next sibling parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Fri, 7 May 2004 13:46:42 -0700, "Walter"
<newshound digitalmars.com> wrote:

"Mike Wynn" <one_mad_alien hotmail.com> wrote in message
news:fmon90dcch9sqi36uqnv33q6vj8s7hf5i7 4ax.com...
 Walter/Digital mars, and any money Walter makes from our sugestions is
 just payment for giving us the D compiler for free.
I haven't made any money whatsoever off of D itself <g>. The idea is to make money doing presentations on D and producing books, articles, training materials, etc.
and anyone who does not buy your book when it comes out deserves cast(FieryPit)
 however with Synesis it is not so clear, why loader.d for instance,
 instead of improving the dynloader.d I posted feb 2003
 http://www.digitalmars.com/drn-bin/wwwnews?D/11102
 which was free for everyone to use and modify and give back to the
 community without charge or restriction, Walter/synesis chose to give
 similar functionality but with restriction.
Matthew has promised to change the license, but it's moot at the moment because we don't agree on the design of loader.d. Be that as it may, there is an ongoing problem here of people posting code like yours - it gets lost in the blizzard of postings. We must do better. I propose one of the two: 1) make a newsgroup digitalmars.D.sourcecode for contributions. 2) add it to the D wiki.
I've put some of my code onto www.dsource.org so its public, and under source control, with the intention that leading by example, others who have open source D projects will do the same and in doing so create a central location for D source so things don't get duplicated (at present there is not a great deal of duplication) I think a D open source projects anouncements news group, ideally moderated so it only has relivant posts would be a fantastic idea, I get the impression that the D community has grown to in the last year, and if it keeps expanding the signal to noise ratio on the news groups will make the situation even worse. to go back over old posts I like the Perl6 approach with requests for comment http://dev.perl.org/perl6/rfc/ apocalypses, exegeses and synopses it may slow development, but when realy pushed I think most ppl would prefer 1 good release to 6 wrong ones. apart from bug releases (and I know a few ppl are waiting for mixins) I think the change from instance Foo(X) Foo_x; to Foo!(X) and allowing class/struct templates was my last major gripe with D. may be now a good time to start getting ppl to design and produce phobos 1.0 ideally LGPL/BSD taking full advantage of D (i.e. classes,templates, buildin types (assoc+growable array) and function which ever gives the most effective solution). Mike.
May 07 2004
prev sibling parent reply resistor AT nospam DOT mac DOT com <resistor_member pathlink.com> writes:
In article <c7gt47$1i46$1 digitaldaemon.com>, Walter says...
Be that as it may, there is an ongoing problem here of people posting code
like yours - it gets lost in the blizzard of postings. We must do better. I
propose one of the two:

1) make a newsgroup digitalmars.D.sourcecode for contributions.
2) add it to the D wiki.
I'd like to add a suggestion 3: bugzilla. If this language is going to take off, it'd really pay off to have the scalability bugzilla offers, and even if it doesn't it works wonders in terms of keeping everything organized. Owen
May 07 2004
parent Brad Anderson <brad sankaty.dot.com> writes:
resistor AT nospam DOT mac DOT com wrote:

 In article <c7gt47$1i46$1 digitaldaemon.com>, Walter says...
 
Be that as it may, there is an ongoing problem here of people posting code
like yours - it gets lost in the blizzard of postings. We must do better. I
propose one of the two:

1) make a newsgroup digitalmars.D.sourcecode for contributions.
2) add it to the D wiki.
I'd like to add a suggestion 3: bugzilla. If this language is going to take off, it'd really pay off to have the scalability bugzilla offers, and even if it doesn't it works wonders in terms of keeping everything organized. Owen
I would add that in deference to Bugzilla, I've been investigating Scarab (http://scarab.tigris.org) and it looks promising. I'd like to get a copy up and running as a test for a project on dsource. Wanna throw some code in for docoa? We could kick the tires on Scarab at the same time... BA
May 07 2004
prev sibling parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Mike Wynn wrote:

 On Fri, 07 May 2004 11:42:08 -0700, "Unknown W. Brackets"
 <unknown at.simplemachines.dot.org> wrote:
 
Ant, I'm sorry, but why do yuo really care that much?  Do you feel that 
your suggestions in this area are worth - what, $50, $100 dollars?  So 
you're donating them to Synesis.  Pah... this is a problem because?
its not a problem its a principle.
Yes, the priniciple of paranoid slashdot-reading, cave-living bats who suspect everything is a conspiracy against them and open source. I'm more scared of them (in the way you're scared of a rabid dog or a lock-away in an asylum) than I am of Synesis owning my code. I bet I could make you have an "episode" by saying that I believe the GPL is... GASP!! not perfect for everyone. Please don't kill too many people before they get you chained down. Don't get me wrong though - I'm a strong supporter of open source and I've contributed code and other things to many open source projects (Mozilla, IE7, PHP, YaBB/YaBB SE, etc. just to name some of the more prolific ones off the top of my head.) and always release my software under a free license (although not always GPL) - but that doesn't mean I'm a paranoid conspiracy theorist. -[Unknown]
May 07 2004
parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Fri, 07 May 2004 14:51:20 -0700, "Unknown W. Brackets"
<unknown at.simplemachines.dot.org> wrote:

Mike Wynn wrote:

 On Fri, 07 May 2004 11:42:08 -0700, "Unknown W. Brackets"
 <unknown at.simplemachines.dot.org> wrote:
 
Ant, I'm sorry, but why do yuo really care that much?  Do you feel that 
your suggestions in this area are worth - what, $50, $100 dollars?  So 
you're donating them to Synesis.  Pah... this is a problem because?
its not a problem its a principle.
Yes, the priniciple of paranoid slashdot-reading, cave-living bats who suspect everything is a conspiracy against them and open source. I'm more scared of them (in the way you're scared of a rabid dog or a lock-away in an asylum) than I am of Synesis owning my code. I bet I could make you have an "episode" by saying that I believe the GPL is... GASP!! not perfect for everyone. Please don't kill too many people before they get you chained down. Don't get me wrong though - I'm a strong supporter of open source and I've contributed code and other things to many open source projects (Mozilla, IE7, PHP, YaBB/YaBB SE, etc. just to name some of the more prolific ones off the top of my head.) and always release my software under a free license (although not always GPL) - but that doesn't mean I'm a paranoid conspiracy theorist. -[Unknown]
Oh, you have me so wrong, I'm not fan of the GPL (prefer the BSD license) I object to companies such as RedHat who have taken GPL'd code and made profit from it, infact I read a report last year that Linux servers cost more to administer than NT4 servers (of course the survey neglected to mention FreeBSD [my OS of chose, XP being the OS I have to use to feed myself]) I'm no paranoid conspiracy theorist, but I've seen enough good intentions corrupted by greed and infighting to stand up for my own beliefs. if you truely believe that open source should be open and free (not just open which is a totally meaning less term,not that free can't have its semantics "adjusted") then you should understand why Ant feels the way he does, and respect his (and my) view rather than resorting to exagersted descriptions of ppl who I would imagine most ppl here also have little time for, unlike ANt who has earned respect for the work he has done. Mike. P.S. I don't read slash-dot (came to D via Dr Dobbs) I'd like to be a bat, you get to fly, and scare women in the shower (without ending up in prison). and the only thing that scares me is politicians! Mike.
May 07 2004
prev sibling next sibling parent "Blandger" <zeroman prominvest.com.ua> writes:
Hi Matthew.

My coin into can.
 3. combined approach, in same module
+1 Regards.
May 07 2004
prev sibling next sibling parent "Blandger" <zeroman prominvest.com.ua> writes:
Hi Matthew.

My coin into can.
 3. combined approach, in same module
+1 Regards.
May 07 2004
prev sibling next sibling parent "Blandger" <zeroman prominvest.com.ua> writes:
Hi Matthew.

My coin into can.
 3. combined approach, in same module
+1 Regards.
May 07 2004
prev sibling next sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
 3. combined approach, in same module
I agree with that. Anyhow, I believe it can be made more specific: The core of the concept of classes is, that they encapsulate data. A class that has only static members should really be considered a module instead. Purely object-oriented languages like Java don't have the concept of free functions, so you are forced to create such module-like classes. In D, it should be avoided, unless there is a good reason to do so. So, up to this point we have one rule: use a class interface, if you encapsulate data, use a free-function-interface, if you don't. The remaining question: if you have a class, which functions should be defined inside as members, which ones outside, as external free functions. For this, one can give a simple ruleto start with: any function that has to access private internals of the class should be defined inside the class. (friend access is, of course, possible inside of modules, but should be avoided unless there is good reason to do so) any other functions, that access the class only via its public interface, should be considered to be moved out of the class as free functions. Of course, there are plenty exceptions to these rules, but at least, these are a first guideline to stick to, unless you see a good reason to do it differently.
May 07 2004
prev sibling next sibling parent Derek <ddparnell bigpond.com> writes:
On Fri, 7 May 2004 18:31:51 +1000, Matthew wrote:

 Walter and I are having a little friendly disagreement which is holding up the
 inclusion of the std.loader module into Phobos.
 
 Basically, it goes like this:
[SNIP]
  The options as I see it are:
 
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
 
 Please let me know your thoughts
Option 4 (as it can be seen as a superset of option 3). A computer programing language is a toolkit. How the coder uses those tools is their decision. If they choose to use a hammer to drive a screw in, so be it on their heads. But remember that a screwdriver makes a very handy paint-tin opener too. A *major* goal for a general-purpose computer language is to make the act of coding easier for people, according to their needs. The designers of such a language ought to facilitate this goal. -- Derek Melbourne, Australia
May 07 2004
prev sibling next sibling parent "Bruno A. Costa" <bruno codata.com.br> writes:
Matthew wrote:


 3. combined approach, in same module
 
 Cheers
 
 Matthew
Matthew, I like the combined approach. But I have to say that Ant is right. Free software developers would be trapped with the Synesis Licence. This is very annoying to us. In fact, Synesis Licence, AFAIK, is incompatible with some widely used free licences (such as GPL). I know you have the right to maintain your code with your licence, and I fully respect it. The problem is that Phobos is to much tied with Synesis code and it would bring trouble to free software projects that use D. Cheers, Bruno.
May 07 2004
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle4 juno.com> writes:
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free
functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
Without seeing the actual declarations I vote for 1. If there is an obvious "object" mental model then go with 2 - and assuming this module is for loading DLLs and such I don't think an object model works very well. For instance, if I hold onto a reference to a DLL object does it keep the dll loaded in memory? More is less: http://www.amazon.com/exec/obidos/tg/detail/-/0060005688/102-3661341-2044918?v=glance
May 07 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Ben Hinkle" <bhinkle4 juno.com> wrote in message
news:c7g4tc$dak$1 digitaldaemon.com...
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free
functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
Without seeing the actual declarations I vote for 1. If there is an obvious "object" mental model then go with 2 - and assuming this module is for loading DLLs and such I don't think an object model works very well. For instance, if I hold onto a reference to a DLL object does it keep the dll loaded in memory? More is less:
http://www.amazon.com/exec/obidos/tg/detail/-/0060005688/102-3661341-2044918?v=glance It's an interesting dilemma. I like the quote "In sum, this book stretches cause and effect in order to sell books to those who want to avoid responsibility for their own decisions", although only, I suppose, because it suits my position in the current debate. In general I'm for orthogonality. For example, the STLSoft string classes don't follow std::basic_string<> and provide a gazillion kitchen sink methods that can be easily emulated with the standard algorithms. I find it interesting to look at the scripting languages. Perl has many ways of doing things; IMO it's overly complex and arbitrary. Python has just one way of doing each thing; IMO it's a complete doddle to use, and is great. Ruby is kind of halfway between the two; IMO it's the best of the three. Go figure!
May 07 2004
prev sibling next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Matthew wrote:
  The options as I see it are:
 
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
 
 Please let me know your thoughts
There's something to be said for unity, I think. I say 1 or 2, depending on how OOPy the library wants to be. If every API had two complete implementations, Phobos would quickly snowball into some freaky monstrosity reminiscent of Perl. :) That being said, I don't think the world would come crashing down if both were there, provided that the semantics of one was clearly defined in terms of the other. (ie two interfaces for one API) -- andy
May 07 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Andy Friesen" <andy ikagames.com> wrote in message
news:c7g80s$iap$1 digitaldaemon.com...
 Matthew wrote:
  The options as I see it are:

 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free
functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest

 Please let me know your thoughts
There's something to be said for unity, I think.
To be sure, in most cases I agree. But I think that enforced unity in all cases is against the spirit of C (http://www.comeaucomputing.com/faqs/genfaq.html#betterCgeneral) - which is a good spirit! - and is too reminiscent of the way of Java, which is, IMO, too much of a nannying approach.
 If every API had two complete implementations, Phobos would quickly
 snowball into some freaky monstrosity reminiscent of Perl. :)
Absolutely true. I only believe that this joint approach is appropriate in a minority of cases. For example, the std.windows.registry module is entirely class-based, as to do otherwise would be an incredible unusable mess, and little better than using the Win32 Reg* API directly.
 That being said, I don't think the world would come crashing down if
 both were there, provided that the semantics of one was clearly defined
 in terms of the other. (ie two interfaces for one API)
For std.loader, the class and free functions share the exact same implementation, except that the former throw exceptions on errors, and the latter return false/null/etc. Hence, there are virtually no additional maintenance considerations. This is, in fact, one of my criteria for determining whether something is suitable for a dual approach. If the combined approach cannot be only, say, 110% or less of the effort of one alone, then I think long and hard about whether the benefits of the freedom of choice is worth the costs of the additional coding/maintenance. It is only such similar modules that I'm advocating for option 3.
May 07 2004
prev sibling next sibling parent "fred" <info fleet-manage.com> writes:
I'm for number 4 !

 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
May 07 2004
prev sibling next sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
Matthew schrieb:
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
For this library, probably no. 1, else probably no. 2. There should be *one* obvious way to accomplish a task. -eye
May 07 2004
prev sibling next sibling parent reply mike parker <mike aldacron.com> writes:
Matthew wrote:

  The options as I see it are:
 
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
that's the way things fall. But the combined approach is wrong, IMO - adds uneeded clutter to Phobos. My feeling is that by using free functions, those who really must have a class can roll their own to wrap the free functions, while those who don't can just get on with it.
May 07 2004
parent C <qbert atari-soldiers.com> writes:
I agree, i honestly think the base library needs to be free functions 
only, then a supllemental library that wraps all the base in OO.

Write now its all sorts of mixed up, with seemingly no structure.  Maybe 
its time to start a phobos alternative.

C

On Sat, 08 May 2004 03:04:18 +0000, mike parker <mike aldacron.com> wrote:

 Matthew wrote:

  The options as I see it are:

 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free 
 functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please 
 suggest
that's the way things fall. But the combined approach is wrong, IMO - adds uneeded clutter to Phobos. My feeling is that by using free functions, those who really must have a class can roll their own to wrap the free functions, while those who don't can just get on with it.
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 07 2004
prev sibling next sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
On Fri, 7 May 2004 18:31:51 +1000, "Matthew"
<matthew.hat stlsoft.dot.org> wrote:

5. Some other combined approach that I've not anticipated. Please suggest
I think I'd probably prefer to see the free functions implemented as static methods in the class. Of course, that's a 100% class-based approach, isn't it??? Well...not really. And, I suppose they're not really free functions if they're implemented as static methods inside of a class, are they? Well....kind of. Anyhow, that's what I'd like to see. But, my runner-up vote is for a mixed approach, all in the same module. --Benji Smith
May 07 2004
parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Benji Smith wrote:

 I think I'd probably prefer to see the free functions implemented as
 static methods in the class. Of course, that's a 100% class-based
 approach, isn't it??? Well...not really.
I must say, this is a lovely idea. Unless I'm mistaken, these could be aliased even to have exactly the affect of free functions, am I wrong? -[Unknown]
May 07 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Unknown W. Brackets" <unknown at.simplemachines.dot.org> wrote in message
news:c7gnu6$1a03$3 digitaldaemon.com...
 Benji Smith wrote:

 I think I'd probably prefer to see the free functions implemented as
 static methods in the class. Of course, that's a 100% class-based
 approach, isn't it??? Well...not really.
I must say, this is a lovely idea. Unless I'm mistaken, these could be aliased even to have exactly the affect of free functions, am I wrong?
In that case, what the user would have is effectively option 3, so I see no effective difference. It is, after all, the user's experience that's largely at issue here. For my part, I don't see any conceptual difference whatsoever between a static method of a class, and a free static function in that class. I have no preference for either, and it would ease the naming issue.
May 07 2004
prev sibling next sibling parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Matthew wrote:

 Please let me know your thoughts
 
 Cheers
 
 Matthew
This is a difficult issue, because it involves both inconsistency and usability. Consider this.... what if printf were a class member? This code: if (number == 0) printf("The number is 0!"); Would then be changed to this in OOP style: if (number == 0) { wannabePrintf printer = new wannabePrintf; printer.data = "The number is 0!"; printer.print(); } (I realize I'm overdoing it a bit, but it's just an example...) Personally, I see this as what I call "OOP overusage". In some cases, I see OOP used just so you can say, "I'm cool because I am using OOP for everything!" But, in some cases this just makes the code more confusing and long.... I see the purpose of OOP to be that of maintainability and abstraction. If functions are strongly linked and have nothing to do with other functions, they should be linked. If, on the other hand, they have only meaning to do with each other, and have no shared variables, and no real reason to be OOP... I don't believe they should be. But then, many will disagree with me. To some, a drawn out example is much more desirable because, well, basically they like OOP. making it so there are too many ways to do things seems like a bad idea. Then again, PHP does it with mysqli - and people like that, and it's not going to make things all that confusing or inconsistent at all. -[Unknown]
May 07 2004
parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7gmg4$189a$1 digitaldaemon.com>, Unknown W. Brackets says...
	if (number == 0)
	{
		wannabePrintf printer = new wannabePrintf;
		printer.data = "The number is 0!";
		printer.print();
	}
(I realize I'm overdoing it a bit, but it's just an example...)

Personally, I see this as what I call "OOP overusage".  In some cases, I 
see OOP used just so you can say, "I'm cool because I am using OOP for 
everything!"  But, in some cases this just makes the code more confusing 
and long....
Actually, it would be more like: formatted_output::printf("the number is 0!"); I don't like this ... but it does have the advantage that the only symbol that get dumped into the table is "formatted_output". Remember, OOP is intended to solve "large program" maintainability problems. It's a weapon designed to go after "mega-fauna" programming problems. In a program with 100,000 functions, this is a real boon. If you are doing a lot of output, you could even do this: class mod_printf { static P(int x) {...} static P(double x) {...} static P(char[] x) {...} // Print in hexadecimal static X(int x) {...} // 0x1234 static X(double x) {...} // not used much static X(char[] x) {...} //"\AA \BC" }; foo(int snum, char[] name) { with(mod_printf) { P("Name ");P(name);P(" in hex [");X(name);P("]\n"); } } Now, P() doesn't clutter the symbol table, but you can write concise code when you want to. (A non-static version could do faster, buffered, output.) Kevin
May 07 2004
parent reply "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Kevin Bealer wrote:
 Actually, it would be more like:
 
 formatted_output::printf("the number is 0!");
I did say I was overdoing it - an example still.
 
 I don't like this ... but it does have the advantage that the only symbol
 that get dumped into the table is "formatted_output".  Remember, OOP is
intended
 to solve "large program" maintainability problems.  It's a weapon designed to
go
 after "mega-fauna" programming problems.  In a program with 100,000 functions,
 this is a real boon.
Yes, but you still have formatted_output in the sumbol table. Before you had printf. Big difference. Yes, in many cases using classes can clean stuff up when you're too, frankly, lazy to establish a clean naming convention. And again, classes have most certainly their place, but using them for no reason is like buying a new truck to transport a single piece of paper.
 
 If you are doing a lot of output, you could even do this:
 
 class mod_printf {
 static P(int x) {...}
 static P(double x) {...}
 static P(char[] x) {...}
 
 // Print in hexadecimal
 static X(int x) {...}    // 0x1234
 static X(double x) {...} // not used much
 static X(char[] x) {...} //"\AA \BC"
 };
 
 foo(int snum, char[] name)
 {
 with(mod_printf) {

 P("Name ");P(name);P(" in hex [");X(name);P("]\n");
 }
 }
 
 Now, P() doesn't clutter the symbol table, but you can write concise code when
 you want to.  (A non-static version could do faster, buffered, output.)
Perhaps so, but this only makes for more confusing code. Which reads easier? with (mod_printf) { P("some text.\n"); P("more test.\n"); P("even more."); } Or... printf("some text.\n"); printf("more test.\n"); printf("even more."); While the hexadecimal functionality is a nice feature, classes can introduce unneccessary complication into simple things. Basically, I agree with Walter's opinion on this. (news://news.digitalmars.com:119/c7gqop$1eoi$1 digitaldaemon.com) The difference for me is that I've always seen OOP as a method to address issues that are caused by deeper problems anyway. But I'm not arguing OOP here, just saying that there are clean reasons for using either. -[Unknown]
May 07 2004
parent reply Kevin Bealer <Kevin_member pathlink.com> writes:
In article <c7gvgv$1log$1 digitaldaemon.com>, Unknown W. Brackets says...
Yes, but you still have formatted_output in the sumbol table.  Before 
you had printf.  Big difference.
Well, printf, sprintf, snprintf, vsprintf, puts, etc.
Yes, in many cases using classes can clean stuff up when you're too, 
frankly, lazy to establish a clean naming convention.  And again, 
classes have most certainly their place, but using them for no reason is 
like buying a new truck to transport a single piece of paper.
.
The difference for me is that I've always seen OOP as a method to 
address issues that are caused by deeper problems anyway.  But I'm not 
arguing OOP here, just saying that there are clean reasons for using either.

-[Unknown]
I agree - putting all those in one object, which contains no state, is not all that great. You can solve the problem better with modules or some other namespace like mechanism, etc. But if all a language has is classes, they get used as modules and namespaces and delegates (ie operator() in C++), and a hundred other things. It's important to solve the namespace crowding problem, but most of the techniques will look similar: provide a grouping mechanism (classes with no non-static methods, or modules, or namespaces), then provide a "uses" mechanism so they don't have to type the wrapper name. Kevin
May 09 2004
parent "Unknown W. Brackets" <unknown at.simplemachines.dot.org> writes:
Kevin Bealer wrote:

 It's important to solve the namespace crowding problem, but most of the
 techniques will look similar:  provide a grouping mechanism (classes with no
 non-static methods, or modules, or namespaces), then provide a "uses" mechanism
 so they don't have to type the wrapper name.
 
 Kevin
I've always thought of this as a possible function for with. That's basically how it's used in JavaScript, and it does make some amount of sense - assuming your class names, namespaces, and variable names are all separate. Then you could also change it to something like: with (varName): Just like with version, etc. I like it better, personally, than the way .NET/etc. handles it where, at least to my recollection, you import namespaces per-file or something. (okay, again, I don't really like OOP generally so I may not be remembering properly.) But this could get ugly... so I'm not going to argue for or against this syntax either. But, yes, I agree with what you said entirely. -[Unknown]
May 11 2004
prev sibling next sibling parent reply Eric Anderton <ericanderton at yahoo dot com> <Eric_member pathlink.com> writes:
 The options as I see it are:

1. free functions only
2. class-interface only
3. combined approach, in same module
4. combined approach, in (for example) std.c.loader.d (for the free functions)
and std.loader.d (for the class)
5. Some other combined approach that I've not anticipated. Please suggest
My vote is for 2, with some suggestions to make free functions work (option 5) My $0.02: A class-only loader can still be made to work with 'free function' dll's, if the dll is simply thought to expose a reference to a 'default' interface of static functions alongside anything else that std.loader wants to add for D classes. It would be good design since the functions are grouped as a unit, as they exist in the library, yet still maintains compatibility with existing dll/dso's. This also avoids duplication of effort when writing an application that may need to use a multitude of different libraries with the same interface: its code you'd have to write anyway. Also, its the most straight-forward approach since everything is grouped in one place, under a single architecture.
May 07 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Unfortunately, because Walter and I've been arguing about the implementation of
this, it may have been misunderstood by the community.

*All* it is is a platform-independent layer over LoadLibrary/GetProcAddress
(Win32) / dlopen/dlsym (Linux).

There is certainly a need for a class loader that builds upon this basic module,
and I'd be happy to participate in that with others later on, but that's not
what's addressed in this module.



"Eric Anderton" <ericanderton at yahoo dot comEric_member pathlink.com> wrote in
message news:c7gn61$1969$1 digitaldaemon.com...
 The options as I see it are:

1. free functions only
2. class-interface only
3. combined approach, in same module
4. combined approach, in (for example) std.c.loader.d (for the free functions)
and std.loader.d (for the class)
5. Some other combined approach that I've not anticipated. Please suggest
My vote is for 2, with some suggestions to make free functions work (option 5) My $0.02: A class-only loader can still be made to work with 'free function' dll's, if
the
 dll is simply thought to expose a reference to a 'default' interface of static
 functions alongside anything else that std.loader wants to add for D classes.

 It would be good design since the functions are grouped as a unit, as they
exist
 in the library, yet still maintains compatibility with existing dll/dso's.
This
 also avoids duplication of effort when writing an application that may need to
 use a multitude of different libraries with the same interface: its code you'd
 have to write anyway.

 Also, its the most straight-forward approach since everything is grouped in one
 place, under a single architecture.
May 07 2004
parent reply Mike Wynn <one_mad_alien hotmail.com> writes:
On Sat, 8 May 2004 07:23:57 +1000, "Matthew"
<matthew.hat stlsoft.dot.org> wrote:

Unfortunately, because Walter and I've been arguing about the implementation of
this, it may have been misunderstood by the community.

*All* it is is a platform-independent layer over LoadLibrary/GetProcAddress
(Win32) / dlopen/dlsym (Linux).
Why ? as I see it (an I may be wrong) Walter is no great fan of extra wrapper for the sake of crossplatform dev when a version(The_OS_I_use) will do. for loading a lib we have the OS dependant operations the ideal approad is to have; alias OS_HANDLE SharedLibHandle; SharedLibHandle loadExtLibrary( TCHAR[] name ); // no '.dll/.so' searches LD_LBRARY_PATH/PATH (os depandant) SharedLibHandle loadExtLibrary( TCHAR[] name, TCHAR[] path ); // no '.dll/.so' just looks in path for the library if you want os dependancy use the OS call! void * getSymbolName( SharedLibHandle lib, TCHAR[] name ); all in a module say vosi (virtual OS interface) every thing else can the use that interface to allow say template loader(T) { T getSymbol( TCHAR[] name, SharedLibHandle lib ) { void * rv = getSymbolname( lib, name ); if ( !rv) throw new NoSuchSymbolException( name ); return cast(T)rv; } T getSymbol(TCHAR[] name, TCHAR[] libname ) { SharedLibHandle lib = loadExtLibrary( libname ); if ( !lib ) throw new NoSuchLibrary( libname ); return getSymbol( lib, name ); } T getSymbol(TCHAR[] name, TCHAR[] libname, TCHAR[] path ) { SharedLibHandle lib = loadExtLibrary( libname, path); if ( !lib ) throw new NoSuchLibrary( libname ); return getSymbol( lib, name ); } }
There is certainly a need for a class loader that builds upon this basic module,
and I'd be happy to participate in that with others later on, but that's not
what's addressed in this module.
now what you want to do with elaborate classes etc is up to you 90% of the uses of dll/so's has been covered above, you will notice that I've not added any calls to unload the libraries, this is simply because without extensive interaction with the GC and/or overloaded return type that behave as proxy items, you can not determine which loaded libraries are still referenced, so load and keep until the process exits and the OS should (will) cleanup for you. Kiss Mike.
May 07 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Mike Wynn" <one_mad_alien hotmail.com> wrote in message
news:lm4o90h50rojbn6tjh7rh2ns49pf2b80hj 4ax.com...
 On Sat, 8 May 2004 07:23:57 +1000, "Matthew"
 <matthew.hat stlsoft.dot.org> wrote:

Unfortunately, because Walter and I've been arguing about the implementation
of
this, it may have been misunderstood by the community.

*All* it is is a platform-independent layer over LoadLibrary/GetProcAddress
(Win32) / dlopen/dlsym (Linux).
Why ? as I see it (an I may be wrong) Walter is no great fan of extra wrapper for the sake of crossplatform dev when a version(The_OS_I_use) will do.
Are you arguing for you, or for Walter?
 for loading a lib we have the OS dependant operations
 the ideal approad is to have;
 alias OS_HANDLE SharedLibHandle;
 SharedLibHandle loadExtLibrary( TCHAR[] name  );
 // no '.dll/.so' searches LD_LBRARY_PATH/PATH (os depandant)
 SharedLibHandle loadExtLibrary( TCHAR[] name, TCHAR[] path  );
 // no '.dll/.so' just looks in path for the library
  if you want os dependancy use the OS call!
 void * getSymbolName( SharedLibHandle lib, TCHAR[] name );
 all in a module say vosi (virtual OS interface)

 every thing else can the use that interface to allow
 say
 template loader(T) {
 T getSymbol( TCHAR[] name, SharedLibHandle lib  ) {
 void * rv = getSymbolname( lib, name );
 if ( !rv) throw new NoSuchSymbolException( name );
 return cast(T)rv;
 }

 T getSymbol(TCHAR[] name, TCHAR[] libname  ) {
 SharedLibHandle lib = loadExtLibrary(  libname );
 if ( !lib ) throw new NoSuchLibrary( libname );
 return getSymbol( lib, name );
 }
 T getSymbol(TCHAR[] name, TCHAR[] libname, TCHAR[] path  ) {
 SharedLibHandle lib = loadExtLibrary( libname, path);
 if ( !lib ) throw new NoSuchLibrary( libname );
 return getSymbol( lib, name );
 }
 }


There is certainly a need for a class loader that builds upon this basic
module,
and I'd be happy to participate in that with others later on, but that's not
what's addressed in this module.
now what you want to do with elaborate classes etc is up to you 90% of the uses of dll/so's has been covered above, you will notice that I've not added any calls to unload the libraries, this is simply because without extensive interaction with the GC and/or overloaded return type that behave as proxy items, you can not determine which loaded libraries are still referenced, so load and keep until the process exits and the OS should (will) cleanup for you. Kiss
I'm sorry, maybe it's me? - I just turned over another year yesterday - but this is just so far beyond anything that I can consider sensible, that I don't see how I can even address your perspective. So I give up. Perhaps it's time for a DSLG?
May 07 2004
parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Sat, 8 May 2004 11:12:23 +1000, "Matthew"
<matthew.hat stlsoft.dot.org> wrote:

"Mike Wynn" <one_mad_alien hotmail.com> wrote in message
news:lm4o90h50rojbn6tjh7rh2ns49pf2b80hj 4ax.com...
 On Sat, 8 May 2004 07:23:57 +1000, "Matthew"
 <matthew.hat stlsoft.dot.org> wrote:

Unfortunately, because Walter and I've been arguing about the implementation
of
this, it may have been misunderstood by the community.

*All* it is is a platform-independent layer over LoadLibrary/GetProcAddress
(Win32) / dlopen/dlsym (Linux).
Why ? as I see it (an I may be wrong) Walter is no great fan of extra wrapper for the sake of crossplatform dev when a version(The_OS_I_use) will do.
Are you arguing for you, or for Walter?
neither, I'm asking you why the need for a cross platform LoadLibrary/GetProcAddress wrapper when there is version(Linux) etc or you can implement the linux dlopen/dlsym with the win32 API or win32 API with dlopen/dlsym.
 for loading a lib we have the OS dependant operations
 the ideal approad is to have;
 alias OS_HANDLE SharedLibHandle;
 SharedLibHandle loadExtLibrary( TCHAR[] name  );
 // no '.dll/.so' searches LD_LBRARY_PATH/PATH (os depandant)
 SharedLibHandle loadExtLibrary( TCHAR[] name, TCHAR[] path  );
 // no '.dll/.so' just looks in path for the library
  if you want os dependancy use the OS call!
 void * getSymbolName( SharedLibHandle lib, TCHAR[] name );
 all in a module say vosi (virtual OS interface)

 every thing else can the use that interface to allow
 say
 template loader(T) {
 T getSymbol( TCHAR[] name, SharedLibHandle lib  ) {
 void * rv = getSymbolname( lib, name );
 if ( !rv) throw new NoSuchSymbolException( name );
 return cast(T)rv;
 }

 T getSymbol(TCHAR[] name, TCHAR[] libname  ) {
 SharedLibHandle lib = loadExtLibrary(  libname );
 if ( !lib ) throw new NoSuchLibrary( libname );
 return getSymbol( lib, name );
 }
 T getSymbol(TCHAR[] name, TCHAR[] libname, TCHAR[] path  ) {
 SharedLibHandle lib = loadExtLibrary( libname, path);
 if ( !lib ) throw new NoSuchLibrary( libname );
 return getSymbol( lib, name );
 }
 }
I'm sorry, maybe it's me? - I just turned over another year yesterday - but this is just so far beyond anything that I can consider sensible, that I don't see how I can even address your perspective. So I give up. Perhaps it's time for a DSLG?
why ? 90% of the times I've used a dll I want to load it, get symbols and use it for the life time of the app, the only time I've every considered unloading a dll was to have upgrade whilst live functionality. what can be simpler than extern (C) { alias int function(int, int) myfunc; } myfunc getPlugin() { return loader( myfunc ).getSymbol( "myfunction", "mydll" ); } main () { //call what ever or myfunc func = getPlugin(); return func( 3, 2 ); } as opposed to extern (C) { alias int function(int, int) myfunc; } myfunc getPlugin(ExeModule mylib ) { return loader( myfunc ).getSymbol( "myfunction", "mydll" ); } main() { auto ExeModule mylib = new ExeModule( "mydll.dll" ); // call what every passing mylib if needed myfunc func = cast(myfunc)mylib.getSymbol( "myfunction" ); } in loader.d I can see a module info classes, but the ref count appears to be module static, and unused by ExeModule, a simple struct ModInfo { HModule lib; int refcount } // where HModule is an OS dependant alias. ModInfo[char[]] loadedlibs; would do (wouldn't it?) to just cache the handles of loaded libs. plz explain why this is beyond what you would consider sencible. Mike.
May 08 2004
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c7fhhj$2gtc$1 digitaldaemon.com...
 Walter believes that every module should have a single, unambiguous API.
Yes.
 He is
 happy for that to be either free functions, or classes, although he would
 probably admit to a preference for classes for most things.
I feel that a class should be used where there is some 'state' to be set and preserved across the function calls, and that free functions should be used when the functionality is stateless. For example, std.regexp has state, and so is a class. std.file functions are all atomic, and so is a collection of free functions. State is a problem that classes are an ideal solution for. Otherwise, your free functions wind up needing state pointers (i.e. 'this' for classes), and organizational control over the construction, destruction, invariants, resource management and exception safety is lost. Furthermore, if the state consists of static data, the free function must also deal with thread safety and synchronization of it. I don't agree with the "everything must be in a class" approach, either, as a function that tests to see if a file exists is atomic and has no state. Why instantiate a class for it? There's a place for both free functions and classes, but I strongly disagree with Matthew's point of view that each module should provide both to access the same functionality. I disagree because: 1) either the free function or the class version is going to be an unfortunate kludge, for the aforementioned reasons. 2) dual interfaces mean double the documentation. 3) dual interfaces mean double the bugs. 4) dual interfaces mean twice as much code to maintain. 5) dual interfaces leads the programmer to wonder why there are two and which he should use. He's got twice as much to learn, for no incremental utility. 6) library bloat. (Matthew points out that 3 and 4 may be mitigated by having the two versions be shells over a lower layer that does the implementation. I counter with another layer being just another source of bugs <g>.)
May 07 2004
next sibling parent reply Derek <ddparnell bigpond.com> writes:
On Fri, 7 May 2004 12:46:46 -0700, Walter wrote:

 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c7fhhj$2gtc$1 digitaldaemon.com...
 Walter believes that every module should have a single, unambiguous API.
Yes.
So do I. The opposite is multiple, ambiguous APIs.
 He is
 happy for that to be either free functions, or classes, although he would
 probably admit to a preference for classes for most things.
I feel that a class should be used where there is some 'state' to be set and preserved across the function calls, and that free functions should be used when the functionality is stateless. For example, std.regexp has state, and so is a class. std.file functions are all atomic, and so is a collection of free functions. State is a problem that classes are an ideal solution for. Otherwise, your free functions wind up needing state pointers (i.e. 'this' for classes), and organizational control over the construction, destruction, invariants, resource management and exception safety is lost. Furthermore, if the state consists of static data, the free function must also deal with thread safety and synchronization of it. I don't agree with the "everything must be in a class" approach, either, as a function that tests to see if a file exists is atomic and has no state. Why instantiate a class for it?
As I was getting ready for bed last night, I was thinking exactly the same thing as this. In fact, the 'state' issue is probably the basis I would use for deciding if a class or free functions would be needed.
 There's a place for both free functions and classes, but I strongly disagree
 with Matthew's point of view that each module should provide both to access
 the same functionality. I disagree because:
It seems that I totally misunderstood Matthew's approach. I agree with Walter here. Functionality should be provided in either free functions *or* a class, but not both. If a set of functionality is provided in one form, but the coder wishes to use the other form, she can write a new module that 'wraps' the supplied form to convert it's interface. -- Derek Melbourne, Australia
May 07 2004
parent Chris Lawson <cl mangler.tinfoilhat.ca> writes:
Derek wrote:
 
 
 It seems that I totally misunderstood Matthew's approach. I agree with
 Walter here. Functionality should be provided in either free functions *or*
 a class, but not both.
 
 If a set of functionality is provided in one form, but the coder wishes to
 use the other form, she can write a new module that 'wraps' the supplied
 form to convert it's interface.
 
 
Although if there's enough people who want to do this, it's going to be a lot more error-prone to have everyone roll their own versus having one maintained API. Chris
May 11 2004
prev sibling next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Walter" <newshound digitalmars.com> wrote in message
news:c7gqop$1eoi$1 digitaldaemon.com...
 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c7fhhj$2gtc$1 digitaldaemon.com...
 Walter believes that every module should have a single, unambiguous API.
Yes.
 He is
 happy for that to be either free functions, or classes, although he would
 probably admit to a preference for classes for most things.
I feel that a class should be used where there is some 'state' to be set and preserved across the function calls, and that free functions should be used when the functionality is stateless. For example, std.regexp has state, and so is a class. std.file functions are all atomic, and so is a collection of free functions. State is a problem that classes are an ideal solution for. Otherwise, your free functions wind up needing state pointers (i.e. 'this' for classes), and organizational control over the construction, destruction, invariants, resource management and exception safety is lost. Furthermore, if the state consists of static data, the free function must also deal with thread safety and synchronization of it.
I don't have a problem with any of that, but I am also a pragmatist, and sometimes the world's not that neat. And in any case, it does not help the issue of the unwelcome exceptions. This absolutist approach mandates that if I only want to "test" something that has only class access, and only use it if it exists, I am constrained to have to deal with exceptions, which, in certain application contexts, are not appropriate. The main reason I wrote this loader was that I wanted to combine it with the std.recls and std.windows.registry modules, and have a great example of succinctness in a useful COM server search and inspection tool. Such a tool would naturally want to be able to use the test-and-use approach, and is (or would have been) the exemplar of my argument.
 I don't agree with the "everything must be in a class" approach, either, as
 a function that tests to see if a file exists is atomic and has no state.
 Why instantiate a class for it?

 There's a place for both free functions and classes, but I strongly disagree
 with Matthew's point of view that each module should provide both to access
 the same functionality. I disagree because:
That's just a self-serving misrepresentation of my views. I do *not* believe that each module should provide both. I believe some some - and judging on the number I've contributed thus far, a small minority - should. That's all.
 1) either the free function or the class version is going to be an
 unfortunate kludge, for the aforementioned reasons.
Not so.
 2) dual interfaces mean double the documentation.
Again, a convenient misrepresentation. Why is it double? How have you arrived at that quantification? It is certainly >1, but that is *all* you can assert.
 3) dual interfaces mean double the bugs.
As per point 2)
 4) dual interfaces mean twice as much code to maintain.
Utter, utter rubbish. The module.d code that you have, and which has sparked this debate, is concrete disproof of that statement.
 5) dual interfaces leads the programmer to wonder why there are two and
 which he should use. He's got twice as much to learn, for no incremental
 utility.
There is merit in this, to be sure. But the ultimate realisation of that argument is Java. Do you want to go there? If you don't, then there have to be some cases in which there is merit in having both options available. It may be that loader.d is not that case, but I was interested in starting this thread in the general principle rather than that specific case.
 6) library bloat.
There certainly is a small amout of bloat. But it's not 200%. Again, it's a case of balancing the tradeoffs. Consider the free functions in loader.d. The totality of the "bloat" is the following (which is 60 / 650 lines of loader.d; that's an extra 9%): public HXModule ExeModule_Load(in char[] moduleName) { return ExeModule_Load_(moduleName, false); } public HXModule ExeModule_AddRef(in HXModule hModule) { return ExeModule_AddRef_(hModule, false); } public void ExeModule_Release(inout HXModule hModule) { ExeModule_Release_(hModule, false); } public void *ExeModule_GetSymbol(inout HXModule hModule, in char[] symbolName) { return ExeModule_GetSymbol_(hModule, symbolName, false); } public char[] ExeModule_Error() { return ExeModule_Error_(); } public char[] ExeModule_GetPath(HXModule hModule) { return ExeModule_GetPath_(hModule, false); }
 (Matthew points out that 3 and 4 may be mitigated by having the two versions
 be shells over a lower layer that does the implementation. I counter with
 another layer being just another source of bugs <g>.)
I certainly do. Again, the implementation of the class in my later version of loader.d is far simpler than the changes that you made to the original. If I'm wrong, please show me. ... Anyway, as I've mentioned in an earlier post, I've already caved to Walter on this, purely in order to get loader.d available. It just means that to use it in the way I want, I've now got to write my own free functions which will wrap the API, e.g. HXModule MyExeModule_Load(in char[] moduleName) { try { ExeModule module = new ExeModule(moduleName); return module.handle; } catch(ExeModuleException) { return null; } } In fact - <sickening realisation>arrgh!</sickening realisation> - I can't do that, because the ExeModule instance owns the loaded module, and when it gets GC'd, the module will be freed, leaving me holding a handle to nothing. The alternative it to provide a detach() method for ExeModule, but then that just encourages mixing programming modes for a given component, something I do *not* advocate . Oh man, this sucks hard. I guess I won' be using the Phobos module that I've contributed to Phobos. How's that for code bloat irony? :(
May 07 2004
next sibling parent "Walter" <newshound digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c7hbu7$27ja$1 digitaldaemon.com...
 It just means that to use it in the way I want, I've now got to write my
own free
 functions which will wrap the API, e.g.

     HXModule MyExeModule_Load(in char[] moduleName)
     {
         try
         {
             ExeModule module = new ExeModule(moduleName);

             return module.handle;
         }
         catch(ExeModuleException)
         {
             return null;
         }
     }

 In fact - <sickening realisation>arrgh!</sickening realisation> - I can't
do
 that, because the ExeModule instance owns the loaded module, and when it
gets
 GC'd, the module will be freed, leaving me holding a handle to nothing.
One solution for this is to make the ExeModule object the handle: typedef ExeModule HXModule; and the GC won't free up the module until there are no more HXModule's. HXModule is an opaque type anyway.
May 07 2004
prev sibling parent Regan Heath <regan netwin.co.nz> writes:
On Sat, 8 May 2004 11:08:26 +1000, Matthew <matthew.hat stlsoft.dot.org> 
wrote:
 It just means that to use it in the way I want, I've now got to write my 
 own free
 functions which will wrap the API, e.g.

     HXModule MyExeModule_Load(in char[] moduleName)
     {
         try
         {
             ExeModule module = new ExeModule(moduleName);

             return module.handle;
         }
         catch(ExeModuleException)
         {
             return null;
         }
     }

 In fact - <sickening realisation>arrgh!</sickening realisation> - I 
 can't do that, because the ExeModule instance owns the loaded module, 
 and when it gets GC'd, the module will be freed, leaving me holding a 
 handle to nothing.

 The alternative it to provide a detach() method for ExeModule, but then 
 that just encourages mixing programming modes for a given component, 
 something I do *not* advocate .

 Oh man, this sucks hard. I guess I won' be using the Phobos module that 
 I've contributed to Phobos. How's that for code bloat irony? :(
Have you considered the 'singleton' approach for your alternate API, eg. ExeModule m; HXModule MyExeModule_Load(in char[] moduleName) { if(m is null) { try { m = new ExeModule(moduleName); } catch (ExeModuleException) { return null; } } return m->handle; } (I'm new to D so the above syntax may not be correct, by the idea is the important part) I know there are threading issues with the singleton approach. But it appears to me a module load *is* a singleton, you only need one per execution. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 09 2004
prev sibling next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Walter wrote:

"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c7fhhj$2gtc$1 digitaldaemon.com...
  

Walter believes that every module should have a single, unambiguous API.
    
Yes.
He is
happy for that to be either free functions, or classes, although he would
probably admit to a preference for classes for most things.
    
I feel that a class should be used where there is some 'state' to be set and preserved across the function calls, and that free functions should be used when the functionality is stateless. For example, std.regexp has state, and so is a class. std.file functions are all atomic, and so is a collection of free functions. State is a problem that classes are an ideal solution for. Otherwise, your free functions wind up needing state pointers (i.e. 'this' for classes), and organizational control over the construction, destruction, invariants, resource management and exception safety is lost. Furthermore, if the state consists of static data, the free function must also deal with thread safety and synchronization of it. I don't agree with the "everything must be in a class" approach, either, as a function that tests to see if a file exists is atomic and has no state. Why instantiate a class for it? There's a place for both free functions and classes, but I strongly disagree with Matthew's point of view that each module should provide both to access the same functionality. I disagree because: 1) either the free function or the class version is going to be an unfortunate kludge, for the aforementioned reasons. 2) dual interfaces mean double the documentation. 3) dual interfaces mean double the bugs. 4) dual interfaces mean twice as much code to maintain. 5) dual interfaces leads the programmer to wonder why there are two and which he should use. He's got twice as much to learn, for no incremental utility. 6) library bloat. (Matthew points out that 3 and 4 may be mitigated by having the two versions be shells over a lower layer that does the implementation. I counter with another layer being just another source of bugs <g>.)
This sounds reasonable. I assumed from Mathews original post that he wasn't duplicating functionality. - Sometimes duplication can be useful, if it makes something easier. That's why we have alias right? - Other times it just makes readability much harder. -- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
prev sibling parent DemmeGod <me demmegod.com> writes:
<tangent>
Actually, in an object oriented system that truely models the computer, the
isFile method would be a function of some sort of filesystem object.  There
is really no suck thing as a truely atomic function, however, in being
practical, one must sacrifice true modeling at times.
</tangent>

Perhaps I should change my handle to "thePurist"

Walter wrote:

 I don't agree with the "everything must be in a class" approach, either,
 as a function that tests to see if a file exists is atomic and has no
 state. Why instantiate a class for it?
May 12 2004
prev sibling next sibling parent reply "Jeroen van Bemmel" <someone somewhere.com> writes:
 The options as I see it are:

 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free 
 functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
Exactly how many functions are we talking about? Are there complex interaction patterns, or is it simply 'loadModule( string )'? If it's really trivial to write a wrapper class I'd go for 1, and perhaps make a 'wrappers' module which contains helper classes for those who feel they cannot do without (so essentially that's your option 4, but not in std.c.loader.d but rather std.wrappers) A class based approach would make most sense when there's a context needed to store some data while invoking different methods from the API. A class with only static methods makes less sense to me, since you already have a mechanism (the module) to group related functionality, using a class for that purpose seems wrong
May 07 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
The basic API is

typedef void    *HXModule;

public HXModule ExeModule_Load(in char[] moduleName);
public HXModule ExeModule_AddRef(in HXModule hModule);
public void ExeModule_Release(inout HXModule hModule);
public void *ExeModule_GetSymbol(inout HXModule hModule, in char[] symbolName);
public char[] ExeModule_Error();
public char[] ExeModule_GetPath(HXModule hModule);

It performs the following:

a. It provides a platform-independent view of dynamic loading
b. It provides a platform-independent module reference-counting
c. It provides thread-specific error information
d. It allows the user to query the module path from a module handle

The class looks like:

public auto class ExeModule
{
/// \name Construction
public:
    this(in HXModule hModule, boolean bTakeOwnership)
    this(char[] moduleName)
    ~this()

/// \name Operations
public:
    void close()

/// \name Accessors
public:
    void *getSymbol(in char[] symbolName)
    void *findSymbol(in char[] symbolName)

/// \name Properties
public:
    HXModule handle()
    char[] path()
}

It performs two services over this API:

a. It provides RAII over the loaded module, by being auto. This is, of course, a
very important thing, and why I would never advocate option 1 myself
b. It throws exceptions in the ctor if the given module cannot be loaded

The class is implemented in terms of the same underlying functions as the free
functions, just that the former throw the ExeModuleException, and the latter do
not.

Anyway, I've caved to Walter's immovability, so we'll be getting option 2 only
in
the next release of Phobos. Apologies to those of you who liked 1, 3 & 4. ;(

"Jeroen van Bemmel" <someone somewhere.com> wrote in message
news:c7gv1m$1l1c$1 digitaldaemon.com...
 The options as I see it are:

 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free
 functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
Exactly how many functions are we talking about? Are there complex interaction patterns, or is it simply 'loadModule( string )'? If it's really trivial to write a wrapper class I'd go for 1, and perhaps make a 'wrappers' module which contains helper classes for those who feel they cannot do without (so essentially that's your option 4, but not in std.c.loader.d but rather std.wrappers) A class based approach would make most sense when there's a context needed to store some data while invoking different methods from the API. A class with only static methods makes less sense to me, since you already have a mechanism (the module) to group related functionality, using a class for that purpose seems wrong
May 07 2004
prev sibling next sibling parent reply resistor AT nospam DOT mac DOT com <resistor_member pathlink.com> writes:
I've talked about this some in other posts, but I'm of the opinion that we need
to have SEPARATE free-
function and class libraries.  Then people who want to write in a C-like style
can just link against the 
one they prefer without having to add in the weight of the class library, and
vice-versa.

As I've said before, I think D attempts to aggregate 3 different programming
styles: pure C, C++, and 


Pure-C programmers want a free-function LIBC equivalent.  This is what I think
Phobos should be.

C++ programmers want an STL equivalent.  This is what the DTL hopefully will be.


separate but still 
standardly distributed library.

Perhaps we can have three standard libraries: Phobos (free-function), Deimos
(class library), and DTL.

Owen

In article <c7fhhj$2gtc$1 digitaldaemon.com>, Matthew says...
Walter and I are having a little friendly disagreement which is holding up the
inclusion of the std.loader module into Phobos.

Basically, it goes like this:

Walter believes that every module should have a single, unambiguous API. He is
happy for that to be either free functions, or classes, although he would
probably admit to a preference for classes for most things.

I believe that what Walter believes is a good thing, except for the fact that I
see that it limits the choices of developers. Some people want to use free
functions, others a class-based approach, others to mix and match as they deem
appropriate. (I'm in the last camp.)

I don't ascribe to the free function-only approach because object-orientation
has
a lot going for it. If people want that exclusively, then C is the language for
them, methinks.

I don't ascribe to the class-only model for the converse reasons - i.e.
sometimes
free functions are more convenient/appropriate - in general, and for the
specific
reason that I don't believe that exceptions represent the "one true
error-handling mechanism", and I don't want to be forced to use them when _I_
deem that it's not appropriate to my requirements. Sometimes I want to write
small utilities and simply get a success/rail result from a function. I
certainly
want this facility with std.loader, as I plan to write version/COM-server
trawling utilities and I don't see it as appropriate to be using exceptions
(since exceptions are for exceptional circumstances, not for testing things, IMO
at least).

Hence, the way I've written loader.d (and some other modules), is that there is
a
free function API, and a thin class (+ exceptions) wrapper over that API. This
affords the flexibility to suit all tastes.

I won't bang on about the advantages of this approach further, as those that
agree already agree, and it's my experience that those who want only a
class-only
approach cannot be persuaded to look at the virtues of the other side. (Walter
asserts that the dual approach makes the code harder to maintain. I assert the
contrary. After much debate, we're both still seeing it our own way. Must be one
of those things, I guess ...)

What I'm interested in is getting a feeling for the general level of support for
the following options.

Before I enumerate those options, let me make it clear that I don't believe this
approach is valid for all modules, far from it. The std.windows.registry,
std.mmfile and the std.perf (not yet included) modules are entirely class-based.
The std.recls module has both, and I have written std.loader as both. It is this
latter that is the sticking point, as Walter does not want to release it in such
a guise.

 The options as I see it are:

1. free functions only
2. class-interface only
3. combined approach, in same module
4. combined approach, in (for example) std.c.loader.d (for the free functions)
and std.loader.d (for the class)
5. Some other combined approach that I've not anticipated. Please suggest

Please let me know your thoughts

Cheers

Matthew
May 07 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
 I've talked about this some in other posts, but I'm of the opinion that we need
 to have SEPARATE free-
 function and class libraries.  Then people who want to write in a C-like style
 can just link against the
 one they prefer without having to add in the weight of the class library, and
 vice-versa.

 As I've said before, I think D attempts to aggregate 3 different programming
 styles: pure C, C++, and


 Pure-C programmers want a free-function LIBC equivalent.  This is what I think
 Phobos should be.

 C++ programmers want an STL equivalent.  This is what the DTL hopefully will
be.

a
 separate but still
 standardly distributed library.

 Perhaps we can have three standard libraries: Phobos (free-function), Deimos
 (class library), and DTL.
It's an interesting point that you make. I also find it interesting that the only issues on which Walter and I've experienced any serious divergence - apart from switch/default - has been on these borders between C/C++ & D and the analogous free-functions & classes. I'm not sure what to make of that at the moment, but I think it's worth some consideration. Anyway, to your point. As I demonstrate in <shameless plug>"Imperfect C++" - coming out in Sept/Oct</shameless plug> - C++ is a very poor module interface language (in fact I reckon it is a complete dead duck at that), but the best module implementation language. Hence, I only ever write dynamic libs with C-APIs. (Of course, that's not to say that I do not pass C++ objects around between such modules. In fact, in "IC++" I demonstrate a fully compiler-independent mechanism for doing just that.) So my approach in C/C++ is always to separate things into layers, somewhat akin to the breakdown you describe. Therefore, I am instincively drawn to your idea, or at least the aspects that pertain to a separation of free-function APIs and the classes that wrap them (or provide an alternate implementation to them). However, D has managed to jettison some of the problems of C++, in regards to modules. For example, D's static initialisation ordering is order-deterministic, and cyclics are banned. This answers one of C++'s big imperfections. (Yes, I also address this in "IC++", with an amusingly anachronistic solution.) So, I think those of us to whom such an approach provides appeal need to be a bit circumspect about such a notion, as it may not be necessary. There may also be practical problems. For example, let's assume that loader.d used the free-function API. It uses TSS (Thread Specific Storage) internally in order to be able to provide a thread-specific error information for failures. The problem with that is that if, say, on Win32, the TLS initialisation function TlsAlloc() fails - which is perfectly possible on some older Win OSs, which had quite tight limits on the number of slots - it needs to throw an exception. But the exception is a class, so there we have the rub. Even free func APIs can depend on classes. Anyway, as to the rest of your idea. I like the idea of a separate Deimos class lib, because many people would not need its contents. It would also mean that it could contain a wider spread of components than would be acceptable in the core library. As for DTL, I would not have a problem with it being a separate library, but I suspect that will not be desirable to the vast majority of D users. I also think it will not really be necessary: it's not going to be very big. It's worth noting that DTL is being designed to also accomodate Java/.NET style collections, without sacrificing efficiency for users who will be following the STL / freaching models of enumeration. Anyway, Deimos and the putative separate DTL would both depend on Phobos. Just my thoughts.
 Owen

 In article <c7fhhj$2gtc$1 digitaldaemon.com>, Matthew says...
Walter and I are having a little friendly disagreement which is holding up the
inclusion of the std.loader module into Phobos.

Basically, it goes like this:

Walter believes that every module should have a single, unambiguous API. He is
happy for that to be either free functions, or classes, although he would
probably admit to a preference for classes for most things.

I believe that what Walter believes is a good thing, except for the fact that
I
see that it limits the choices of developers. Some people want to use free
functions, others a class-based approach, others to mix and match as they deem
appropriate. (I'm in the last camp.)

I don't ascribe to the free function-only approach because object-orientation
has
a lot going for it. If people want that exclusively, then C is the language
for
them, methinks.

I don't ascribe to the class-only model for the converse reasons - i.e.
sometimes
free functions are more convenient/appropriate - in general, and for the
specific
reason that I don't believe that exceptions represent the "one true
error-handling mechanism", and I don't want to be forced to use them when _I_
deem that it's not appropriate to my requirements. Sometimes I want to write
small utilities and simply get a success/rail result from a function. I
certainly
want this facility with std.loader, as I plan to write version/COM-server
trawling utilities and I don't see it as appropriate to be using exceptions
(since exceptions are for exceptional circumstances, not for testing things,
IMO
at least).

Hence, the way I've written loader.d (and some other modules), is that there
is a
free function API, and a thin class (+ exceptions) wrapper over that API. This
affords the flexibility to suit all tastes.

I won't bang on about the advantages of this approach further, as those that
agree already agree, and it's my experience that those who want only a
class-only
approach cannot be persuaded to look at the virtues of the other side. (Walter
asserts that the dual approach makes the code harder to maintain. I assert the
contrary. After much debate, we're both still seeing it our own way. Must be
one
of those things, I guess ...)

What I'm interested in is getting a feeling for the general level of support
for
the following options.

Before I enumerate those options, let me make it clear that I don't believe
this
approach is valid for all modules, far from it. The std.windows.registry,
std.mmfile and the std.perf (not yet included) modules are entirely
class-based.
The std.recls module has both, and I have written std.loader as both. It is
this
latter that is the sticking point, as Walter does not want to release it in
such
a guise.

 The options as I see it are:

1. free functions only
2. class-interface only
3. combined approach, in same module
4. combined approach, in (for example) std.c.loader.d (for the free functions)
and std.loader.d (for the class)
5. Some other combined approach that I've not anticipated. Please suggest

Please let me know your thoughts

Cheers

Matthew
May 07 2004
next sibling parent mike parker <mike aldacron.com> writes:
Matthew wrote:
 it will not really be necessary: it's not going to be very big. It's worth
noting
 that DTL is being designed to also accomodate Java/.NET style collections,
 without sacrificing efficiency for users who will be following the STL /
 freaching models of enumeration.
If you're speaking of supporting something like: Iterator it = myCollection.iterator(); while(it.hasNext()) { MyObject o = (MyObject)iterator.next(); } I'd say hang it. I've been using Java for quite some time, and I'm not in the minority when I say that syntax stinks. Having used the new 1.5 foreach syntax: for(MyObject o : myCollection) { } ... and after many discussions with other Java types, I believe you won't be hurting anyone's feelings by leaving it out.
May 08 2004
prev sibling parent Mike Wynn <one_mad_alien hotmail.com> writes:
On Sat, 8 May 2004 12:51:55 +1000, "Matthew"
<matthew.hat stlsoft.dot.org> wrote:

 For example, D's static initialisation ordering is order-deterministic,
and cyclics are banned. 
can you post some code that shows this, as from my experiance (see bug posting about static initialisers within templated classes ) the order is not as you would expect (even order of declaration would be enough) Mike.
May 08 2004
prev sibling parent Robert Jones <robertjones21 HotPOP.com> writes:
Matthew wrote:
 Walter and I are having a little friendly disagreement which is holding up the
 inclusion of the std.loader module into Phobos.
 
 Basically, it goes like this:
 
 Walter believes that every module should have a single, unambiguous API. He is
 happy for that to be either free functions, or classes, although he would
 probably admit to a preference for classes for most things.
 
 I believe that what Walter believes is a good thing, except for the fact that I
 see that it limits the choices of developers. Some people want to use free
 functions, others a class-based approach, others to mix and match as they deem
 appropriate. (I'm in the last camp.)
 
 I don't ascribe to the free function-only approach because object-orientation
has
 a lot going for it. If people want that exclusively, then C is the language for
 them, methinks.
 
 I don't ascribe to the class-only model for the converse reasons - i.e.
sometimes
 free functions are more convenient/appropriate - in general, and for the
specific
 reason that I don't believe that exceptions represent the "one true
 error-handling mechanism", and I don't want to be forced to use them when _I_
 deem that it's not appropriate to my requirements. Sometimes I want to write
 small utilities and simply get a success/rail result from a function. I
certainly
 want this facility with std.loader, as I plan to write version/COM-server
 trawling utilities and I don't see it as appropriate to be using exceptions
 (since exceptions are for exceptional circumstances, not for testing things,
IMO
 at least).
 
 Hence, the way I've written loader.d (and some other modules), is that there
is a
 free function API, and a thin class (+ exceptions) wrapper over that API. This
 affords the flexibility to suit all tastes.
 
 I won't bang on about the advantages of this approach further, as those that
 agree already agree, and it's my experience that those who want only a
class-only
 approach cannot be persuaded to look at the virtues of the other side. (Walter
 asserts that the dual approach makes the code harder to maintain. I assert the
 contrary. After much debate, we're both still seeing it our own way. Must be
one
 of those things, I guess ...)
 
 What I'm interested in is getting a feeling for the general level of support
for
 the following options.
 
 Before I enumerate those options, let me make it clear that I don't believe
this
 approach is valid for all modules, far from it. The std.windows.registry,
 std.mmfile and the std.perf (not yet included) modules are entirely
class-based.
 The std.recls module has both, and I have written std.loader as both. It is
this
 latter that is the sticking point, as Walter does not want to release it in
such
 a guise.
 
  The options as I see it are:
 
 1. free functions only
 2. class-interface only
 3. combined approach, in same module
 4. combined approach, in (for example) std.c.loader.d (for the free functions)
 and std.loader.d (for the class)
 5. Some other combined approach that I've not anticipated. Please suggest
 
 Please let me know your thoughts
 
 Cheers
 
 Matthew
 
 
I perfer number 4, however it seems to me that Walter is against it for fear that it would get out of hand and turn Phobos into a quagmire. I have not encountered Matthew's problem personally, but I can see where he coming from. Perhaps if too many people end up in the sameplace, someone will write another runtime library(flibd - Free D library?)?
May 07 2004