July 13, 2006
Derek Parnell wrote:
> On Thu, 13 Jul 2006 05:05:22 +1000, Walter Bright 
>> It's not always true, but languages that are less wordy in their example code tend to be picked up faster. People's first projects in D aren't going to be large, complex, professional products. They'll want to just try it out on something simple. That bar should be as low as reasonable.
> 
> I understand your desire to not 'frighten' new comers away. My concern is that your "low as reasonable" seems to encourage poor programming practices. Can you provide an example where the 'import' and 'visibility' ideas being brainstormed at the moment would force example code to look scary? At worst, someone might have to add 'public { ... }' somewhere.

Not exactly what you're after, but consider the Java hello world program:

  class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
  }

There's a reason for everything there, but it's a little off-putting. Consider the D version:

  import std.stdio;

  void main() {
     writefln("Hello World!");
  }

I can go straighter towards what I want to do, without detouring through all the other requirements Java puts on things that seem, with such a simple program, to be beside the point.

Just for fun, here's an Ada version:

  With STANDARD_IO;
  Use STANDARD_IO;
  Procedure HELLO_WORLD is begin
    Put("Hello world!");
  End HELLO_WORLD;

No thanks! <g>
July 13, 2006
Georg Wrede wrote:
> Walter Bright wrote:
>> But when writing illustrative sample code, I feel that having to add in 'public's is distracting from the point (unless, of course, the point is about how access control works!). I see this a lot in sample C++ code, and it is distracting, to me anyway.
> 
> Problem is, readers of illustrative code tend to copy them in their own first programs, then make similar code, and in time larger pieces of code. They frequently miss the transition point where they should change their behavior (in this case, to start using "private"), and the end result is large code with small-code practices. Very bad, and you can see it all over the place!

A good point.

>> And it's just plain irritating when writing smaller programs where access control is quite irrelevant.
> 
> Code should be written so implicitly public imports are not needed!
> 
> If I import some high-level module which in turn imports some low-level module, and I happen to need stuff from that low-level module too, I sure as hell better import that explicitly in my program.

I think when two modules are somewhat tightly coupled, public import should be used instead of manually importing everything all over again. It's pretty analogous to the package management systems of modern Linux distros: installing (importing) a package (module) also installs (imports) its dependencies.

IMO the biggest issue here is that even practice shows that private imports are much much more common. It's quiet natural since the main principle of OOP languages is to keep public interfaces as minimal as possible. It's annoying as hell to publicly import everything. At first it looks like it's much easier to code that way. After ~50 classes the future still looks quite bright. But then you import that simple helloworld-widget from GUI or some other huge library (I'm talking about QT 4.2 sized GUI here, not DUI). Bang - 50+ name conflicts. Why did this happen? Because too much functionality was exposed to the child modules. If only that graphical arbitrary precision math library object hadn't imported that 3rd party implementation of sound stream. Importing to a namespace (import foo as bar) can be used as a workaround, but it really isn't the solution. It should only be used in some "rare" situations, where refactoring otherwise becomes too expensive. (at least that's how I see it)

Specifying the correct protection attribute for every import isn't a trivial task at all. I think one should spend significant amount of time considering the rationale behind every import. The task can be impossibly difficult for even experienced programmers and therefore should be made as "safe" (=does not poison namespace) as possible. Luckily importing privately by default fixes this.

-- 
Jari-Matti
July 13, 2006
On Wed, 12 Jul 2006 17:03:11 -0700, Walter Bright wrote:

> Derek Parnell wrote:
>> On Thu, 13 Jul 2006 05:05:22 +1000, Walter Bright
>>> It's not always true, but languages that are less wordy in their example code tend to be picked up faster. People's first projects in D aren't going to be large, complex, professional products. They'll want to just try it out on something simple. That bar should be as low as reasonable.
>> 
>> I understand your desire to not 'frighten' new comers away. My concern is that your "low as reasonable" seems to encourage poor programming practices. Can you provide an example where the 'import' and 'visibility' ideas being brainstormed at the moment would force example code to look scary? At worst, someone might have to add 'public { ... }' somewhere.
> 
> Not exactly what you're after, but consider the Java hello world program:
> 
>    class HelloWorldApp {
>      public static void main(String[] args) {
>          System.out.println("Hello World!");
>      }
>    }
> 
> There's a reason for everything there, but it's a little off-putting. Consider the D version:
> 
>    import std.stdio;
> 
>    void main() {
>       writefln("Hello World!");
>    }

Thank you! This is exactly what I had hoped for, because the changes
discussed recently would not alter this example one iota. In fact, the
changes only start to kick in when programs get more complex, and that's
exactly when you need to introduce such protection concepts to D newcomers.

> I can go straighter towards what I want to do, without detouring through all the other requirements Java puts on things that seem, with such a simple program, to be beside the point.
> 
> Just for fun, here's an Ada version:
> 
>    With STANDARD_IO;
>    Use STANDARD_IO;
>    Procedure HELLO_WORLD is begin
>      Put("Hello world!");
>    End HELLO_WORLD;
> 
> No thanks! <g>

Ouch! And I just remembered what it would look like in COBOL (oh the
horror!)

Here it is in Euphoria (one line) ...

  puts(1, "Hello world!")

but now we digress because Euphoria's import (include) system is almost as problematic as D's. In that language one can have independent third party libraries clashing with each other just because you decided to include both of them into your application, even if you never reference the clashing members.

But back on track, the sample code in the D tutorials will have zero changes in nearly every case, and minor changes in the others to explain how the protection system can work in the coder's favour.
-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
13/07/2006 10:17:13 AM
July 13, 2006
Walter Bright wrote:
> Derek Parnell wrote:
>> On Thu, 13 Jul 2006 05:05:22 +1000, Walter Bright
>>> It's not always true, but languages that are less wordy in their example code tend to be picked up faster. People's first projects in D aren't going to be large, complex, professional products. They'll want to just try it out on something simple. That bar should be as low as reasonable.
>>
>> I understand your desire to not 'frighten' new comers away. My concern is that your "low as reasonable" seems to encourage poor programming practices. Can you provide an example where the 'import' and 'visibility' ideas being brainstormed at the moment would force example code to look scary? At worst, someone might have to add 'public { ... }' somewhere.
> 
> Not exactly what you're after, but consider the Java hello world program:
> 
>   class HelloWorldApp {
>     public static void main(String[] args) {
>         System.out.println("Hello World!");
>     }
>   }
> 
> There's a reason for everything there, but it's a little off-putting. Consider the D version:
> 
>   import std.stdio;
> 
>   void main() {
>      writefln("Hello World!");
>   }

Changing the language syntax so that imports are private by default does not change anything in either of those examples. Perhaps this is a better example:

module gfx_subsystem:
  private import GUI;

  void init_gfx_system() { setvideomode(); clearbuffers(); ... }

module game_engine:
  (private) import gfx_subsystem, sound_subsystem;

  void init_engine() { init_gfx_system(); ... }

Here the developer of game_engine is really not interested in GUI widgets. If gfx_subsystem publicly imported the GUI stuff, the namespace of game_engine would be totally poisoned. Then why should it be the default behavior? After all, this is a very common pattern in applications programming. Using public imports also makes the development process a lot more time consuming. Think of all the irrelevant proposals the IDE shows when auto-completing code in a poisoned namespace.

-- 
Jari-Matti
July 13, 2006
Walter Bright wrote:
> Derek Parnell wrote:
> 
>> On Thu, 13 Jul 2006 05:05:22 +1000, Walter Bright
>>
>>> It's not always true, but languages that are less wordy in their example code tend to be picked up faster. People's first projects in D aren't going to be large, complex, professional products. They'll want to just try it out on something simple. That bar should be as low as reasonable.
>>
>>
>> I understand your desire to not 'frighten' new comers away. My concern is that your "low as reasonable" seems to encourage poor programming practices. Can you provide an example where the 'import' and 'visibility' ideas being brainstormed at the moment would force example code to look scary? At worst, someone might have to add 'public { ... }' somewhere.
> 
> 
> Not exactly what you're after, but consider the Java hello world program:
> 
>   class HelloWorldApp {
>     public static void main(String[] args) {
>         System.out.println("Hello World!");
>     }
>   }
> 
> There's a reason for everything there, but it's a little off-putting. Consider the D version:
> 
>   import std.stdio;
> 
>   void main() {
>      writefln("Hello World!");
>   }
> 
> I can go straighter towards what I want to do, without detouring through all the other requirements Java puts on things that seem, with such a simple program, to be beside the point.
> 
> Just for fun, here's an Ada version:
> 
>   With STANDARD_IO;
>   Use STANDARD_IO;
>   Procedure HELLO_WORLD is begin
>     Put("Hello world!");
>   End HELLO_WORLD;
> 
> No thanks! <g>


And the concise & completely safe D version:

   import std.stdio io;

   void main() {
      io.writefln("Hello World!");
   }

However, this example imports only the one module, so use of the unsafe import might be ok for such things?

On the other hand, someone pointed out that habits are formed from just such examples (was it Derek?). One should perhaps be careful to ensure the safe approach is /encouraged/ right from the start, if such habits are indeed formed in this manner? That's a question for another time.


> I can go straighter towards what I want to do, without detouring
> through all the other requirements Java puts on things that seem,
> with such a simple program, to be beside the point.

If concise language is considered beneficial, then D would likely gain from a less wordy safe-import (in terms of overal usage).


> I can go straighter towards what I want to do, without detouring
> through all the other requirements Java puts on things that seem,
> with such a simple program, to be beside the point.

Then why detour with an extra alais statement?

    import lib.db.model.odbc odbc;

    void main() {
       auto db = odbc.open ("db");
    }

versus this:

    static import lib.db.model.odbc;
    alias lib.db.model.odbc odbc;

    void main() {
       auto db = odbc.open ("db");
    }

To echo your own sentiment, No thanks! <g>


the latter looks rather like the Ada version.

>   With STANDARD_IO;
>   Use STANDARD_IO;
>   Procedure HELLO_WORLD is begin
>     Put("Hello world!");
>   End HELLO_WORLD;


July 13, 2006
Jari-Matti Mäkelä wrote:
> Georg Wrede wrote:
> 
>>Walter Bright wrote:
>>
>>>But when writing illustrative sample code, I feel that having to add
>>>in 'public's is distracting from the point (unless, of course, the
>>>point is about how access control works!). I see this a lot in sample
>>>C++ code, and it is distracting, to me anyway.
>>
>>Problem is, readers of illustrative code tend to copy them in their own
>>first programs, then make similar code, and in time larger pieces of
>>code. They frequently miss the transition point where they should change
>>their behavior (in this case, to start using "private"), and the end
>>result is large code with small-code practices. Very bad, and you can
>>see it all over the place!
> 
> 
> A good point.
> 
> 
>>>And it's just plain irritating when writing smaller programs where
>>>access control is quite irrelevant.
>>
>>Code should be written so implicitly public imports are not needed!
>>
>>If I import some high-level module which in turn imports some low-level
>>module, and I happen to need stuff from that low-level module too, I
>>sure as hell better import that explicitly in my program.
> 
> 
> I think when two modules are somewhat tightly coupled, public import
> should be used instead of manually importing everything all over again.
> It's pretty analogous to the package management systems of modern Linux
> distros: installing (importing) a package (module) also installs
> (imports) its dependencies.
> 
> IMO the biggest issue here is that even practice shows that private
> imports are much much more common. It's quiet natural since the main
> principle of OOP languages is to keep public interfaces as minimal as
> possible. It's annoying as hell to publicly import everything. At first
> it looks like it's much easier to code that way. After ~50 classes the
> future still looks quite bright. But then you import that simple
> helloworld-widget from GUI or some other huge library (I'm talking about
> QT 4.2 sized GUI here, not DUI). Bang - 50+ name conflicts. Why did this
> happen? Because too much functionality was exposed to the child modules.
> If only that graphical arbitrary precision math library object hadn't
> imported that 3rd party implementation of sound stream. Importing to a
> namespace (import foo as bar) can be used as a workaround, but it really
> isn't the solution. It should only be used in some "rare" situations,
> where refactoring otherwise becomes too expensive. (at least that's how
> I see it)
> 
> Specifying the correct protection attribute for every import isn't a
> trivial task at all. I think one should spend significant amount of time
> considering the rationale behind every import. The task can be
> impossibly difficult for even experienced programmers and therefore
> should be made as "safe" (=does not poison namespace) as possible.
> Luckily importing privately by default fixes this.
> 


All good points.

In the FWIW category, Mango makes all imports private expect for those that expose symbols used somewhere important; such as arguments to class constructors. The idea was first proposed by Chris Nicholson-Sauls, and it is one I found to pay big dividends overall (thanks to Chris).

I noticed that an import count was performed on Mango, and the public imports were 18% or something? That seems high to me, so perhaps we've been slacking ;D

Either way, all imports in Mango are (or should be) explicit in terms of public, private, package, etc. When it comes to code, it is often useful to explicitly convey intent behind an action.
July 13, 2006
Walter Bright wrote:
> Derek Parnell wrote:
>> On Wed, 12 Jul 2006 01:00:32 -0700, Walter Bright wrote:
>>> I was quite surprised at the negative reaction to it from the people who suggested those changes.
>>
>> Just to clarify, not *all* people who suggested those changes that you
>> implemented were upset by you doing that. I use AAs a lot and I love the
>> changes you made to them. 
> 
> Thanks for letting me know that. It does make me feel better about that episode.

I can't remember what I said at the time (if anything), but I think they work fine as well.
July 13, 2006
Lars Ivar Igesund wrote:
> Walter Bright wrote:
> 
>> Lars Ivar Igesund wrote:
>>> Walter Bright wrote:
>>>
>>>> Lars Ivar Igesund wrote:
>>>>> Well, who did ever say that was a good idea, everything public by
>>>>> default? ;)
>>>> I did <g>.
>>> Right :) I don't agree.
>> Let me explain why I think default public is a good idea.
>>
>> It reduces clutter in sample, example, and quick programs. Access
>> security is an advanced feature, one that's invaluable for a complex
>> project, but is just in the way for smaller ones.
>>
>> I don't mind at all when crafting a carefully designed, reusable module
>> that 'private' needs to be explicit. It helps document the intention,
>> and lends the impression that the designer did put some thought into the
>> code.
>>
>> But when writing illustrative sample code, I feel that having to add in
>> 'public's is distracting from the point (unless, of course, the point is
>> about how access control works!). I see this a lot in sample C++ code,
>> and it is distracting, to me anyway.
>>
>> And it's just plain irritating when writing smaller programs where
>> access control is quite irrelevant.
> 
> And it here I think you miss the point. When D as a language rather help in
> writing small example programs, instead of making it easy and safe to write
> large applications and libraries, how is then D supposed to take the
> ultimate step? D has so much potential for writing large, powerful
> applications and libraries, and D continously shoots it down. Illustrative
> code should show the actual features making the language good to use in
> larger projects (once they are there, they will contain much larger bodies
> of code than all the smaller ones combined), not be a goal for the language
> itself.
> 

It would take a lot of large changes to make D ill-suited to easily developed and concise example programs or utilities compared to any of its strongly type competitors. None of the recent import proposals come even close to doing that.

In fact, such large changes would probably do harm to both types of development because D as-is is almost perfect IMO. We're just trying to tune the import mechanism here, especially for use with the forthcoming huge and diverse libraries. :)
July 13, 2006
Walter Bright wrote:
> Derek Parnell wrote:
> 
>> On Thu, 13 Jul 2006 05:05:22 +1000, Walter Bright
>>
>>> It's not always true, but languages that are less wordy in their example code tend to be picked up faster. People's first projects in D aren't going to be large, complex, professional products. They'll want to just try it out on something simple. That bar should be as low as reasonable.
>>
>>
>> I understand your desire to not 'frighten' new comers away. My concern is that your "low as reasonable" seems to encourage poor programming practices. Can you provide an example where the 'import' and 'visibility' ideas being brainstormed at the moment would force example code to look scary? At worst, someone might have to add 'public { ... }' somewhere.

(I've been trying to catch up on this NG, but the number of unreads is growing faster than I can keep up, so I don't know what the Current Community Consensus on syntax exactly is right now, so I'm guessing the syntax here.)

> Not exactly what you're after, but consider the Java hello world program:
> 
>   class HelloWorldApp {
>     public static void main(String[] args) {
>         System.out.println("Hello World!");
>     }
>   }
> 
> There's a reason for everything there, but it's a little off-putting. 

Yes, from a teacher's point of view, the above is just depressing. On first day, you can't even explain the words because the needed concepts are pure greek to the audience anyway. I've actually been there a few times.

> Consider the D version:
> 
>   import std.stdio;
> 
>   void main() {
>      writefln("Hello World!");
>   }

D is a lot nicer. Now compare the above with:


    import std.stdio as io;

    void main() {
        io.writefln("Hello World!");
    }


Sure it's more to type! (Six letters, a dot and two spaces.)

From an educational point of view, this is actually better than current D, because it now becomes perfectly clear /why/ we have the import line in the first place!!! It's needed for the writefln.

Additionally, I've seen students struggling with what comes from which library, why we need so many libraries, etc. All this would become much clearer if the students keep seeing "which words don't belong to the language itself and come from a library instead".

> I can go straighter towards what I want to do, without detouring through all the other requirements Java puts on things that seem, with such a simple program, to be beside the point.

I can, however, see this:

    import std.stdio as io;

    void main() {
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
        io.writefln("Hello World!");
    }

Now it's three letters more per line, so in a 100kloc program this means 300kB extra on the hard disk, and some wear on your fingertips.

I admit we could have a means of using unqualified names, sure. But that should be the programmer's own choice!

    import std.stdio;                 // works like currently
    import std.stdio as foo;          // into foo namespace only
    import std.stdio.writefln;        // only writefln gets imported
    import std.stdio.writefln as wrt; // please implement this too

(Oh, and "as" is better than a space, if you ask me. No question.)
July 14, 2006
On Thu, 13 Jul 2006 10:22:41 +0300, Georg Wrede wrote:

> 
> I can, however, see this:
> 
>      import std.stdio as io;
> 
>      void main() {
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>          io.writefln("Hello World!");
>      }

Just half joking, but what you can do even now is this ...

      import std.stdio;
      alias std.stdio.writefln w;

      void main() {
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
          w("Hello World!");
      }

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
14/07/2006 10:35:41 AM