www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - imports in functions

reply Walter Bright <newshound2 digitalmars.com> writes:
Nobody seems to have noticed yet, but yesterday I removed the restriction 
preventing import declarations from being used in functions. These now work:

void test1()
{
     import std.c.stdio;
     printf("hello world\n");
}

void test2()
{
     static import std.c.stdio;
     std.c.stdio.printf("hello world\n");
}

https://github.com/D-Programming-Language/dmd/commit/d5fbd53aa8d8452dce2514944575e654d387477a

I believe this can lead to better encapsulation of code, especially when using 
mixins, versioning and other conditional compilation constructs.
Jun 12 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/12/2011 04:15 PM, Walter Bright wrote:
 Nobody seems to have noticed yet, but yesterday I removed the
 restriction preventing import declarations from being used in functions.
 These now work:

 void test1()
 {
 import std.c.stdio;
 printf("hello world\n");
 }

 void test2()
 {
 static import std.c.stdio;
 std.c.stdio.printf("hello world\n");
 }

 https://github.com/D-Programming-Language/dmd/commit/d5fbd53aa8d8452dce2514944575e654d387477a


 I believe this can lead to better encapsulation of code, especially when
 using mixins, versioning and other conditional compilation constructs.

Fabulous. std.benchmark already uses the feature, and from a mixin no less: https://github.com/andralex/phobos/commit/c5f2778a0fc393d6bd17ebec4765b28937575c31 One interesting aspect of the feature is that if import is used from within a template, it's not actually imported unless the template is instantiated. Andrei
Jun 12 2011
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
This is awesome!

Another benefit here is code running programs are simplified. For
"D script" kind of things, a technique I use is to simply wrap some
code inside a main function. Almost every feature worked there -
nested functions, structs, classes, etc. Now imports do too! Yay!
Jun 12 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 06/12/2011 04:33 PM, Adam D. Ruppe wrote:
 This is awesome!

 Another benefit here is code running programs are simplified. For
 "D script" kind of things, a technique I use is to simply wrap some
 code inside a main function. Almost every feature worked there -
 nested functions, structs, classes, etc. Now imports do too! Yay!

This bodes well for your "run this online" thing, too. All we need to do is wrap a main() around the example code and it should work. Andrei
Jun 12 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-12 15:08, Andrej Mitrovic wrote:
 This seems like a way to simulate namespaces in C++, right? I wouldn't
 know, but it looks similar to that 'using foo' trick.

C++ namespaces are completely different. Everything in a namespace has to be referenced by its namespace explicitly unless you use using. So, without using, you need to do stuff like std::vector<int> v; whereas with using namespace std; vector<int> v; you don't need the std:: tag anymore. Using namespace affects _everything_ after it, which is why it's pretty much verboten in header files (otherwise it would pollute the global namespace). And whether you have a using statement or not, as soon as you #include a file, everything in it is visible in the current file. Namespaces just segregate the names so that they don't clash. D modules are very different. As soon as you import a module, everything in that module is visible (though you can't use anything in it unless it's public or the current module is in the same package and it's package or if you're deriving from class in that module and the symbol in question is protected). You don't have to use the module name when using _any_ of its symbols unless names clash or you imported the module statically. It's kind of like you automatically have a using statement all of the time, except that it's much more sophisticated and handles name clashes much better. By importing within a function, you're saying that only that function has access to the symbols within the module being imported. As for as the rest of the module is concerned, the imported module does not actually exist. You're restricting what can see it. So, I'm not quite sure what you mean by this simulating C++ namespaces. They both deal with how symbols are brought into and viewable in the current file, but they're very different. - Jonathan M Davis
Jun 12 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/13/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
< snip>

So much for my blurry recollection of C++ features. :-)
Jun 12 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/12/11 5:08 PM, Andrej Mitrovic wrote:
 This seems like a way to simulate namespaces in C++, right? I wouldn't
 know, but it looks similar to that 'using foo' trick.

I hope not :o). C++ namespaces are quite lacking. Andrei
Jun 12 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
This seems like a way to simulate namespaces in C++, right? I wouldn't
know, but it looks similar to that 'using foo' trick.
Jun 12 2011
prev sibling next sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Sun, 12 Jun 2011 14:15:27 -0700, Walter Bright wrote:

 Nobody seems to have noticed yet, but yesterday I removed the
 restriction preventing import declarations from being used in functions.
 These now work:
 
 void test1()
 {
      import std.c.stdio;
      printf("hello world\n");
 }
 
 void test2()
 {
      static import std.c.stdio;
      std.c.stdio.printf("hello world\n");
 }
 
 https://github.com/D-Programming-Language/dmd/commit/

 
 I believe this can lead to better encapsulation of code, especially when
 using mixins, versioning and other conditional compilation constructs.

Cool! This is a definite improvement. :) -Lars
Jun 12 2011
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 13.06.2011 1:15, Walter Bright wrote:
 Nobody seems to have noticed yet, but yesterday I removed the 
 restriction preventing import declarations from being used in 
 functions. These now work:

 void test1()
 {
     import std.c.stdio;
     printf("hello world\n");
 }

 void test2()
 {
     static import std.c.stdio;
     std.c.stdio.printf("hello world\n");
 }

 https://github.com/D-Programming-Language/dmd/commit/d5fbd53aa8d8452dce25
4944575e654d387477a 


 I believe this can lead to better encapsulation of code, especially 
 when using mixins, versioning and other conditional compilation 
 constructs.

Also very helpful for unittests, thanks. -- Dmitry Olshansky
Jun 12 2011
prev sibling next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 12/06/2011 22:15, Walter Bright wrote:
 Nobody seems to have noticed yet, but yesterday I removed the
 restriction preventing import declarations from being used in functions.
 These now work:

 void test1()
 {
 import std.c.stdio;
 printf("hello world\n");
 }

 void test2()
 {
 static import std.c.stdio;
 std.c.stdio.printf("hello world\n");
 }

 https://github.com/D-Programming-Language/dmd/commit/d5fbd53aa8d8452dce2514944575e654d387477a


 I believe this can lead to better encapsulation of code, especially when
 using mixins, versioning and other conditional compilation constructs.

I did notice this - I think it's awesome. So many times when debugging code I've attempted to write import std.stdio; in the function, then had to move it away from the code I was debugging - of course this left a stray import because I forgot about it :3 -- Robert http://octarineparrot.com/
Jun 13 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Btw, it's disappointing that I can't call split with a separator at
compile-time:

enum result = split("bla, bla");  // ok
enum result = split("bla, bla", ",");  // nope
Jun 13 2011
parent KennyTM~ <kennytm gmail.com> writes:
On Jun 14, 11 03:55, Andrej Mitrovic wrote:
 Btw, it's disappointing that I can't call split with a separator at
 compile-time:

 enum result = split("bla, bla");  // ok
 enum result = split("bla, bla", ",");  // nope

That's due to (at least) http://d.puremagic.com/issues/show_bug.cgi?id=4047.
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Walter, it looks like this addition inadvertently fixes the issue of
DLLs not linkable due to Phobos imports.

I've had this DLL (alongside with dllmodule.d which had initialization
calls inside DLLMain):
module EdrLib;

import std.utf;

pragma(lib, "gdi32.lib");
pragma(lib, "comdlg32.lib");
import win32.windef;
import win32.wingdi;

export extern(Windows) BOOL EdrCenterText(HDC hdc, PRECT prc, string pString)
{
     SIZE size ;
     GetTextExtentPoint32(hdc, pString.toUTF16z, pString.length, &size) ;
     return TextOut(hdc, (prc.right - prc.left - size.cx) / 2,
                         (prc.bottom - prc.top - size.cy) / 2,
pString.toUTF16z, pString.length);
}

The header file produced from this would cause any client code which
imports the header to look for ModuleInitZ, which wouldn't exist in
the generated import library since it's an import library and not a
static library.

But, if I move the phobos import inside the EdrCenterText function:

export extern(Windows) BOOL EdrCenterText(HDC hdc, PRECT prc, string pString)
{
     import std.utf;

     SIZE size ;
     GetTextExtentPoint32(hdc, pString.toUTF16z, pString.length, &size) ;
     return TextOut(hdc, (prc.right - prc.left - size.cx) / 2,
                         (prc.bottom - prc.top - size.cy) / 2,
pString.toUTF16z, pString.length);
}

Then it works. My related bug report about this (and its complicated
to read due to various misunderstanding on my part) is
http://d.puremagic.com/issues/show_bug.cgi?id=6019.

But it's great that there's an actual workaround now!
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
When I add module ctors/dtors, I get the ModuleInfoZ shenanigans again.
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
And they do run, I've tested it in a non-DLL example.
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm guessing this is what you're after:

http://codepad.org/TCtG68Fw
http://codepad.org/65GBDjPS

rdmd main.d
shared ctor!
ctor!
foo.test
dtor!
shared dtor!
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Should DLLs even have module ctors/dtors?

I think this is what DLLMain's DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH
and their detach counterparts are for.
Jun 13 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Well it seems to work fine. :)
Jun 13 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm having some fun with this.

import std.array;

void main()
{
    with (namespace!("std.stdio std.algorithm std.range"))
    {
        auto squares = map!("a * a")([2, 4, 6]);
        writeln(squares);
    }
}

template namespace(string x)
{
    mixin(namespaceImpl(x));
}

string namespaceImpl(string x)
{
    string result;
    auto mods = split(x);
    foreach (val; mods)
    {
        result ~= "import " ~ val ~ ";";
    }
    return result;
}
Jun 13 2011
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On 6/13/2011 8:28 PM, Andrej Mitrovic wrote:
 Walter, it looks like this addition inadvertently fixes the issue of
 DLLs not linkable due to Phobos imports.
 
 I've had this DLL (alongside with dllmodule.d which had initialization
 calls inside DLLMain):
 module EdrLib;
 
 import std.utf;
 
 pragma(lib, "gdi32.lib");
 pragma(lib, "comdlg32.lib");
 import win32.windef;
 import win32.wingdi;
 
 export extern(Windows) BOOL EdrCenterText(HDC hdc, PRECT prc, string pString)
 {
      SIZE size ;
      GetTextExtentPoint32(hdc, pString.toUTF16z, pString.length, &size) ;
      return TextOut(hdc, (prc.right - prc.left - size.cx) / 2,
                          (prc.bottom - prc.top - size.cy) / 2,
 pString.toUTF16z, pString.length);
 }
 
 The header file produced from this would cause any client code which
 imports the header to look for ModuleInitZ, which wouldn't exist in
 the generated import library since it's an import library and not a
 static library.
 
 But, if I move the phobos import inside the EdrCenterText function:
 
 export extern(Windows) BOOL EdrCenterText(HDC hdc, PRECT prc, string pString)
 {
      import std.utf;
 
      SIZE size ;
      GetTextExtentPoint32(hdc, pString.toUTF16z, pString.length, &size) ;
      return TextOut(hdc, (prc.right - prc.left - size.cx) / 2,
                          (prc.bottom - prc.top - size.cy) / 2,
 pString.toUTF16z, pString.length);
 }
 
 Then it works. My related bug report about this (and its complicated
 to read due to various misunderstanding on my part) is
 http://d.puremagic.com/issues/show_bug.cgi?id=6019.
 
 But it's great that there's an actual workaround now!

This makes me think that there's actually a bug in the function-local imports. I'm guessing they don't run module-level ctors and dtors for the imported modules. Would you mind putting together a test case to check? Thanks, Brad
Jun 13 2011
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On 6/13/2011 8:48 PM, Andrej Mitrovic wrote:
 I'm guessing this is what you're after:
 
 http://codepad.org/TCtG68Fw
 http://codepad.org/65GBDjPS
 
 rdmd main.d
 shared ctor!
 ctor!
 foo.test
 dtor!
 shared dtor!

Actually, not what I was thinking. I was thinking something like this: file 1: import std.stdio; // or inside this, not what I'm testing. static this() { writeln("foo"); } file 2: void main() { import file1; }
Jun 13 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-06-12 23:15, Walter Bright wrote:
 Nobody seems to have noticed yet, but yesterday I removed the
 restriction preventing import declarations from being used in functions.
 These now work:

 void test1()
 {
 import std.c.stdio;
 printf("hello world\n");
 }

 void test2()
 {
 static import std.c.stdio;
 std.c.stdio.printf("hello world\n");
 }

 https://github.com/D-Programming-Language/dmd/commit/d5fbd53aa8d8452dce2514944575e654d387477a


 I believe this can lead to better encapsulation of code, especially when
 using mixins, versioning and other conditional compilation constructs.

This is awesome. -- /Jacob Carlborg
Jun 17 2011
next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
On 6/19/11 5:20 AM, Andrej Mitrovic wrote:
 This is such a great debugging tool. I mean ddbg is great on its own.
 But being able to quickly import std.stdio and do a few debug writes
 in some library function is fantastic.

print-debugging is so common... in Ruby you always have "puts" available, no need to require anything. Why not do the same for D?
Jun 19 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-06-20 05:18, Ary Manzana wrote:
 On 6/19/11 5:20 AM, Andrej Mitrovic wrote:
 This is such a great debugging tool. I mean ddbg is great on its own.
 But being able to quickly import std.stdio and do a few debug writes
 in some library function is fantastic.

print-debugging is so common... in Ruby you always have "puts" available, no need to require anything. Why not do the same for D?

"puts", don't you use "p"? Shorter and prints better information. -- /Jacob Carlborg
Jun 20 2011
parent Ary Manzana <ary esperanto.org.ar> writes:
On 6/20/11 3:04 PM, Jacob Carlborg wrote:
 On 2011-06-20 05:18, Ary Manzana wrote:
 On 6/19/11 5:20 AM, Andrej Mitrovic wrote:
 This is such a great debugging tool. I mean ddbg is great on its own.
 But being able to quickly import std.stdio and do a few debug writes
 in some library function is fantastic.

print-debugging is so common... in Ruby you always have "puts" available, no need to require anything. Why not do the same for D?

"puts", don't you use "p"? Shorter and prints better information.

Ah, yes, you are right. I use it. p "!" is my battle horse.
Jun 20 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I think I've just found the first bug:

module test;
void main()
{
}

void foo()
{
    import std.utf;
    "bla".toUTF16z;
}

Error: undefined identifier module test.toUTF16z

UFCS doesn't work with function imports. This is a bug, right?
Jun 19 2011
parent "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.1030.1308543325.14074.digitalmars-d puremagic.com...
I think I've just found the first bug:

 module test;
 void main()
 {
 }

 void foo()
 {
    import std.utf;
    "bla".toUTF16z;
 }

 Error: undefined identifier module test.toUTF16z

 UFCS doesn't work with function imports. This is a bug, right?

UFCS barely works at all in D2. Another example: Regression(2.020) Array member call syntax can't find matches in current class http://d.puremagic.com/issues/show_bug.cgi?id=4525
Jun 20 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/21/11, Nick Sabalausky <a a.a> wrote:
 UFCS barely works at all in D2. Another example:

Couple that with the classically buggy 'with' statement and you've got yourself a party! \o/
Jun 20 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Aaaargh, I've used function imports, completely disregarding that
they're not present in 2.053 and now I can't deploy code to github
because people won't be able to compile it.

Ahh the joys.. Well I'm glad I caught this now before embarrassing myself.
Jun 20 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
This is such a great debugging tool. I mean ddbg is great on its own.
But being able to quickly import std.stdio and do a few debug writes
in some library function is fantastic.
Jun 18 2011