Thread overview
coding practices: include whole module or only the needed function
Oct 06, 2014
AsmMan
Oct 06, 2014
bearophile
Oct 06, 2014
H. S. Teoh
Oct 07, 2014
ketmar
Oct 07, 2014
Gary Willoughby
Oct 07, 2014
monarch_dodra
Oct 07, 2014
bachmeier
Oct 07, 2014
ketmar
Oct 07, 2014
monarch_dodra
Oct 07, 2014
ketmar
October 06, 2014
Which practice do you use: if you need only one or two functions from a module:

import myModule : func, func2;

or (import whole module, assuming no function name conflits of course)

import myModule;

any words why one over the other are welcome.

I like the first one why it explicitly show why I'm importing such a module and I think (personally) it make code more easy to read/understand/maitain. Also it's very useful inside functions (local imports) where we can "overload" the function like in:

int f(int arg)
{
   import foo : f;

   return f(somethingElse, arg);
}

I used it recently.
October 06, 2014
AsmMan:

> import myModule : func, func2;

I use this in D to know what I have imported and where is was imported from.

Bye,
bearophile
October 06, 2014
On Mon, Oct 06, 2014 at 09:24:54PM +0000, AsmMan via Digitalmars-d-learn wrote:
> Which practice do you use: if you need only one or two functions from a module:
> 
> import myModule : func, func2;
> 
> or (import whole module, assuming no function name conflits of course)
> 
> import myModule;
> 
> any words why one over the other are welcome.
> 
> I like the first one why it explicitly show why I'm importing such a module and I think (personally) it make code more easy to read/understand/maitain.

Agreed. Recently, I realized more and more that local imports are the way to go if you want maintainable code, specifically, easily- refactorable code.

My old C/C++ habit was to put all imports at the top of the file, but the problem with that is, when you need to break a source file into several smaller files, it's a pain to figure out which imports are used by which pieces of code. It's either that, or copy all the imports everywhere, which is wasteful when one of the new files doesn't actually need most of the imports.

Explicitly naming imported symbols is also important, especially given the recent bugs related to introducing unwanted symbol conflicts into a scope. It also tells you exactly what symbols a particular piece of code depends on; for example, mymodule.d may import std.algorithm, but it's not clear exactly what in std.algorithm is actually used, and where. Specifically importing std.algorithm : find in func1() and std.algorithm : nextPermutation in the respective scopes that need it, makes the code more maintainable -- readers can quickly find out where 'find' and 'nextPermutation' come from without needing to search the docs (or memorize function names).

Then when you need to move func1() and func2() new files, you know that
newfile1.d only depends on std.algorithm.find, and newfile2.d only
depends on std.algorithm.nextPermutation. So next time you rewrite the
code in func1() and you realize that find() is no longer needed, you can
delete the import statement without worrying that it will break other
parts of the code.

Having said that, though, the *disadvantage* of using scoped explicit imports is that if you use a lot of symbols from a particular module, or use the same symbol in many scattered places, then your import statements could become rather unwieldy and repetitive:

	module mymodule;

	void func1(...) {
		import std.algorithm : find, canFind, nextPermutation,
			remove, /* a huge long list here */;
		import std.range : isForwardRange;
		import std.array : front, empty, popFront;
		...
	}

	void func2(...) {
		import std.algorithm : canFind, remove,
			cartesianProduct, /* another huge long list
			here, repeating many items from previous list
			*/;
		import std.range : isInputRange;
		import std.array : front, empty, popFront;
		...
	}

So depending on circumstances, sometimes I'd just get lazy and just use a generic import instead.

Of course, the example above is extreme... normally, you don't need to use 20 functions from std.algorithm inside a single function; usually just a small handful is enough. So the above situation should be rather rare. I also find that in practice, it's my own modules (rather than Phobos modules) that tend to have symbols that get used repeatedly; in that case I just use a generic import for that. The one exception is std.range, which tends to be needed everywhere if you write range-based code a lot. Usually I just stick `import std.range` at the top of the file in that case.


> Also it's very useful inside functions (local imports) where we can
> "overload" the function like in:
> 
> int f(int arg)
> {
>    import foo : f;
> 
>    return f(somethingElse, arg);
> }
> 
> I used it recently.

I'm not sure this is a good idea! It makes the code harder to understand, and if it's a team project, you can bet that one day, somebody will come and introduce a bug because he/she refactored the code but failed to notice that the two 'f's refer to two different things. I'd much rather use the renaming feature of imports:

	int f(int arg)
	{
		import foo : fooF = f;
		return fooF(somethingElse, arg);
	}


T

-- 
It only takes one twig to burn down a forest.
October 07, 2014
On Mon, 06 Oct 2014 21:24:54 +0000
AsmMan via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> Which practice do you use: if you need only one or two functions from a module:
> 
> import myModule : func, func2;
> 
> or (import whole module, assuming no function name conflits of course)
> 
> import myModule;
> 
> any words why one over the other are welcome.
in C days i was writting something like this:

  #include "something.h"  // i need foo() and bar()

in D such comments can be turned to direct instructions to the compiler. ;-)

i tend to import "std.stdio" and "std.string" as a whole at the top of the module (sometimes some other "std." also), and doing local imports with explicit function enumeration when i need something from other modules. local imports rocks! ;-)


October 07, 2014
On Monday, 6 October 2014 at 21:24:56 UTC, AsmMan wrote:
> Which practice do you use: if you need only one or two functions from a module:
>
> import myModule : func, func2;
>
> or (import whole module, assuming no function name conflits of course)
>
> import myModule;
>
> any words why one over the other are welcome.
>
> I like the first one why it explicitly show why I'm importing such a module and I think (personally) it make code more easy to read/understand/maitain. Also it's very useful inside functions (local imports) where we can "overload" the function like in:
>
> int f(int arg)
> {
>    import foo : f;
>
>    return f(somethingElse, arg);
> }
>
> I used it recently.

Be mindful of this classic bug: https://issues.dlang.org/show_bug.cgi?id=314
October 07, 2014
On Tuesday, 7 October 2014 at 07:33:24 UTC, Gary Willoughby wrote:
> On Monday, 6 October 2014 at 21:24:56 UTC, AsmMan wrote:
>> Which practice do you use: if you need only one or two functions from a module:
>>
>> import myModule : func, func2;
>>
>> or (import whole module, assuming no function name conflits of course)
>>
>> import myModule;
>>
>> any words why one over the other are welcome.
>>
>> I like the first one why it explicitly show why I'm importing such a module and I think (personally) it make code more easy to read/understand/maitain. Also it's very useful inside functions (local imports) where we can "overload" the function like in:
>>
>> int f(int arg)
>> {
>>   import foo : f;
>>
>>   return f(somethingElse, arg);
>> }
>>
>> I used it recently.
>
> Be mindful of this classic bug: https://issues.dlang.org/show_bug.cgi?id=314

Yeah. In the current state of affairs, please NEVER do selective imports in global scope. As a general rule, avoid imports in global scope anyways.
October 07, 2014
On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra wrote:
> As a general rule, avoid imports in global scope anyways.

Can you expand or provide a link to the issue?
October 07, 2014
On Tue, 07 Oct 2014 17:24:40 +0000
bachmeier via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra wrote:
> > As a general rule, avoid imports in global scope anyways.
> Can you expand or provide a link to the issue?
ahem...
https://issues.dlang.org/show_bug.cgi?id=313
https://issues.dlang.org/show_bug.cgi?id=314


October 07, 2014
On Tuesday, 7 October 2014 at 17:29:45 UTC, ketmar via Digitalmars-d-learn wrote:
> On Tue, 07 Oct 2014 17:24:40 +0000
> bachmeier via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
> wrote:
>
>> On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra wrote:
>> > As a general rule, avoid imports in global scope anyways.
>> Can you expand or provide a link to the issue?
> ahem...
> https://issues.dlang.org/show_bug.cgi?id=313
> https://issues.dlang.org/show_bug.cgi?id=314

That's only relative to having selective imports.

The idea of avoiding global imports is mostly to avoid polluting your own namespace, or to keep better track of who needs what.

For example, if 1 function requires "std.foo", and then you later remove that function. With global imports, chances are you'll forget to remove it.
October 07, 2014
On Tue, 07 Oct 2014 19:38:52 +0000
monarch_dodra via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> wrote:

> On Tuesday, 7 October 2014 at 17:29:45 UTC, ketmar via Digitalmars-d-learn wrote:
> > On Tue, 07 Oct 2014 17:24:40 +0000
> > bachmeier via Digitalmars-d-learn
> > <digitalmars-d-learn@puremagic.com>
> > wrote:
> >
> >> On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra wrote:
> >> > As a general rule, avoid imports in global scope anyways.
> >> Can you expand or provide a link to the issue?
> > ahem...
> > https://issues.dlang.org/show_bug.cgi?id=313
> > https://issues.dlang.org/show_bug.cgi?id=314
> 
> That's only relative to having selective imports.
ah, i see. sorry, i misread the question.