May 07, 2004
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("Struct #"); X(snum); P("\n");
> 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
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
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
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
"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
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
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
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 08, 2004
"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 08, 2004
"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?