www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - coding practices: include whole module or only the needed function

reply "AsmMan" <jckj33 gmail.com> writes:
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.
Oct 06 2014
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
AsmMan:

 import myModule : func, func2;
I use this in D to know what I have imported and where is was imported from. Bye, bearophile
Oct 06 2014
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
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.
Oct 06 2014
prev sibling next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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=20
 from a module:
=20
 import myModule : func, func2;
=20
 or (import whole module, assuming no function name conflits of=20
 course)
=20
 import myModule;
=20
 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! ;-)
Oct 06 2014
prev sibling parent reply "Gary Willoughby" <dev nomad.so> writes:
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
Oct 07 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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.
Oct 07 2014
parent reply "bachmeier" <no spam.com> writes:
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?
Oct 07 2014
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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=3D313 https://issues.dlang.org/show_bug.cgi?id=3D314
Oct 07 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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.
Oct 07 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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=20
 Digitalmars-d-learn wrote:
 On Tue, 07 Oct 2014 17:24:40 +0000
 bachmeier via Digitalmars-d-learn=20
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Tuesday, 7 October 2014 at 08:37:59 UTC, monarch_dodra=20
 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=3D313 https://issues.dlang.org/show_bug.cgi?id=3D314
=20 That's only relative to having selective imports.
ah, i see. sorry, i misread the question.
Oct 07 2014