Movatterモバイル変換


[0]ホーム

URL:


D Logo
Menu
Search

Language Reference

table of contents

Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.Requires a signed-in GitHub account. This works well for small changes.If you'd like to make larger changes you may want to consider usinga local clone.

Modules

Contents
  1. Module Declaration
    1. Deprecated modules
  2. Import Declaration
    1. Symbol Name Lookup
    2. Public Imports
    3. Static Imports
    4. Renamed Imports
    5. Selective Imports
    6. Renamed and Selective Imports
    7. Scoped Imports
  3. Module Scope Operator
  4. Static Construction and Destruction
    1. Order of Static Construction
    2. Order of Static Construction within a Module
    3. Order of Static Destruction
  5. Order of Unit tests
  6. Mixin Declaration
  7. Package Module
Module:ModuleDeclarationModuleDeclarationDeclDefsDeclDefs
DeclDefs:DeclDefDeclDefDeclDefs
DeclDef:AttributeSpecifierDeclarationConstructorDestructorPostblitInvariantUnitTestAliasThisStaticConstructorStaticDestructorSharedStaticConstructorSharedStaticDestructorConditionalDeclarationDebugSpecificationVersionSpecificationMixinDeclarationEmptyDeclaration
EmptyDeclaration:;

Modules have a one-to-one correspondence with source files. When notexplicitly set via aModuleDeclaration, a module's name defaultsto the name of the file stripped of its path and extension.

A module's name automatically acts as a namespace scope for its contents. Modulessuperficially resemble classes, but differ in that:

Modules can be grouped into hierarchies calledpackages.

Modules offer several guarantees:

Module Declaration

TheModuleDeclaration sets the name of the module and what package itbelongs to. If absent, the module name is taken to be the same name (stripped ofpath and extension) of the source file name.

ModuleDeclaration:ModuleAttributesoptmoduleModuleFullyQualifiedName;
ModuleAttributes:ModuleAttributeModuleAttributeModuleAttributes
ModuleAttribute:DeprecatedAttributeUserDefinedAttribute
ModuleFullyQualifiedName:ModuleNamePackages.ModuleName
ModuleName:Identifier
Packages:PackageNamePackages.PackageName
PackageName:Identifier

TheIdentifiers preceding the rightmostIdentifier are thePackages that themodule is in. The packages correspond to directory names in the source filepath. Package and module names cannot beKeywords.

If present, theModuleDeclaration must be the first and only such declarationin the source file, and may be preceded only by comments and#line directives.

Example:

module c.stdio;// module stdio in the c package

By convention, package and module names are all lower case. This is becausethese names have a one-to-one correspondence with the operating system'sdirectory and file names, and many file systems are not case sensitive. Using alllower case package and module names will avoid or minimize problems when moving projectsbetween dissimilar file systems.

If the file name of a module is an invalid module name (e.g.foo-bar.d), use a module declaration to set a valid module name:

module foo_bar;
Implementation Defined:
  1. The mapping of package and module identifiers to directory and file names.
Best Practices:
  1. PackageNames andModuleNames should be composed of the ASCII characters lower case letters, digits or_ to ensure maximum portability and compatibility with various file systems.
  2. The file names for packages and modules should be composed only of the ASCII lower case letters, digits, and_s, and should not be aKeyword.

Deprecated modules

AModuleDeclaration can have an optionalDeprecatedAttribute. The compiler will produce a message when the deprecatedmodule is imported.

deprecatedmodule foo;
module bar;import foo;// Deprecated: module foo is deprecated

ADeprecatedAttribute can have an optionalAssignExpression argument to provide amore informative message. TheAssignExpression must evaluate to a string at compile time.

deprecated("Please use foo2 instead.")module foo;
module bar;import foo;// Deprecated: module foo is deprecated - Please use foo2 instead.
Implementation Defined:
  1. How the deprecation messages are presented to the user.

Import Declaration

Symbols from one module are made available in another module by using theImportDeclaration:

ImportDeclaration:importImportList;static importImportList;
ImportList:ImportImportBindingsImport,ImportList
Import:ModuleFullyQualifiedNameModuleAliasIdentifier=ModuleFullyQualifiedName
ImportBindings:Import:ImportBindList
ImportBindList:ImportBindImportBind,ImportBindList
ImportBind:IdentifierIdentifier=Identifier
ModuleAliasIdentifier:Identifier

There are several forms of theImportDeclaration, from generalized tofine-grained importing.

The order in whichImportDeclarations occur has no significance.

ModuleFullyQualifiedNames in theImportDeclaration must be fullyqualified with whatever packages they are in. They are not considered to berelative to the module that imports them.

Implementation Defined:
  1. How the compiler resolves the package and module identifiers in an import declaration to its corresponding source files.

Symbol Name Lookup

The simplest form of importing is to just list the modules being imported:

module myapp.main;import std.stdio;// import module stdio from package stdclass Foo : BaseClass{import myapp.foo;// import module myapp.foo in this class' scopevoid bar ()    {import myapp.bar;// import module myapp.bar in this function' scope        writeln("hello!");// calls std.stdio.writeln    }}

When a symbol name is used unqualified, a two-phase lookup is used.First, the module scope is searched, starting from the innermost scope.For example, in the previous example, while looking forwriteln,the order will be:

If the first lookup isn't successful, a second one is performed on imports.In the second lookup phase inherited scopes are ignored. This includes the scope ofbase classes and interfaces (in this example,BaseClass's importswould be ignored), as well as imports in mixed-intemplate.

Symbol lookup stops as soon as a matching symbol is found. If two symbols with thesame name are found at the same lookup phase, this ambiguity will result in acompilation error.

module A;void foo();void bar();
module B;void foo();void bar();
module C;import A;void foo();void test(){    foo();// C.foo() is called, it is found before imports are searched    bar();// A.bar() is called, since imports are searched}
module D;import A;import B;void test(){    foo();// error, A.foo() or B.foo() ?    A.foo();// ok, call A.foo()    B.foo();// ok, call B.foo()}
module E;import A;import B;alias foo = B.foo;void test(){    foo();// call B.foo()    A.foo();// call A.foo()    B.foo();// call B.foo()}

Public Imports

By default, imports areprivate. This means that if module A importsmodule B, and module B imports module C, then names inside C are visible only insideB and not inside A.

An import can be explicitly declaredpublic, which will causenames from the imported module to be visible to further imports. So in the aboveexample where module A imports module B, if module Bpublicly importsmodule C, names from C will be visible in A as well.

All symbols from a publicly imported module are also aliased in theimporting module. Thus in the above example if C contains the name foo, it willbe accessible in A asfoo,B.foo andC.foo.

For another example:

module W;void foo() { }
module X;void bar() { }
module Y;import W;publicimport X;...foo();// calls W.foo()bar();// calls X.bar()
module Z;import Y;...foo();// error, foo() is undefinedbar();// ok, calls X.bar()X.bar();// dittoY.bar();// ok, Y.bar() is an alias to X.bar()

Static Imports

A static import requires the use of a fully qualified nameto reference the module's names:

staticimport std.stdio;void main(){    writeln("hello!");// error, writeln is undefined    std.stdio.writeln("hello!");// ok, writeln is fully qualified}

Renamed Imports

A local name for an import can be given, through which all references to themodule's symbols must be qualified with:

import io = std.stdio;void main(){    io.writeln("hello!");// ok, calls std.stdio.writeln    std.stdio.writeln("hello!");// error, std is undefined    writeln("hello!");// error, writeln is undefined}
Best Practices: Renamed imports are handy when dealing with very long import names.

Selective Imports

Specific symbols can be exclusively imported from a module and bound intothe current namespace:

import std.stdio : writeln, foo = write;void main(){    std.stdio.writeln("hello!");// error, std is undefined    writeln("hello!");// ok, writeln bound into current namespace    write("world");// error, write is undefined    foo("world");// ok, calls std.stdio.write()    fwritefln(stdout,"abc");// error, fwritefln undefined}

static cannot be used with selective imports.

Renamed and Selective Imports

When renaming and selective importing are combined:

import io = std.stdio : foo = writeln;void main(){    writeln("bar");// error, writeln is undefined    std.stdio.foo("bar");// error, foo is bound into current namespace    std.stdio.writeln("bar");// error, std is undefined    foo("bar");// ok, foo is bound into current namespace,// FQN not required    io.writeln("bar");// ok, io=std.stdio bound the name io in// the current namespace to refer to the entire//   module    io.foo("bar");// error, foo is bound into current namespace,// foo is not a member of io}

Scoped Imports

Import declarations may be used at any scope. For example:

void main(){import std.stdio;    writeln("bar");}

The imports are looked up to satisfy any unresolved symbols at that scope.Imported symbols may hide symbols from outer scopes.

In function scopes, imported symbols only become visible after the importdeclaration lexically appears in the function body. In other words, importedsymbols at function scope cannot be forward referenced.

void main(){void writeln(string) {}void foo()    {        writeln("bar");// calls main.writelnimport std.stdio;        writeln("bar");// calls std.stdio.writelnvoid writeln(string) {}        writeln("bar");// calls main.foo.writeln    }    writeln("bar");// calls main.writeln    std.stdio.writeln("bar");// error, std is undefined}

Module Scope Operator

A leading dot (.) causes the identifier to be looked up in the module scope.

constint x = 1;void main(){int x = 5;assert(x == 5);// main.x, not global xassert(.x == 1);// global x}

Static Construction and Destruction

Static constructors are executed to initialize a module's state. Static destructors terminate a module's state.

A module may have multiple static constructors and static destructors. The static constructors are run in lexical order, the static destructors are run in reverse lexical order.

Non-shared static constructors and destructors are run whenever threads are created or destroyed, including the main thread.

Shared static constructors are run once beforemain() is called. Shared static destructors are run after themain() function returns.

import resource;Resource x;shared Resource y;__gshared Resource z;staticthis()// non-shared static constructor{    x = acquireResource();}sharedstaticthis()// shared static constructor{    y = acquireSharedResource();    z = acquireSharedResource();}static ~this()// non-shared static destructor{    releaseResource(x);}sharedstatic ~this()// shared static destructor{    releaseSharedResource(y);    releaseSharedResource(z);}
Best Practices:
  1. Shared static constructors and destructors are used to initialize and terminate shared global data.
  2. Non-shared static constructors and destructors are used to initialize and terminate thread local data.

Order of Static Construction

Shared static constructors on all modules are run before any non-shared staticconstructors.

The order of static initialization is implicitly determined by theimport declarations in each module. Each module is assumed to depend on anyimported modules being statically constructed first.There is no other order imposed on the execution of module static constructors.

Cycles (circular dependencies) in the import declarations are allowed solong as neither, or one, but not both, of the modules, contains static constructors or staticdestructors. Violation of this rule will result in a runtime exception.

Implementation Defined:
  1. An implementation may provide a means of overriding the cycle detection abort. A typical method uses the D Runtime switch--DRT-oncycle=... where the following behaviors are supported:
    1. abort The default behavior. The normal behavior as described in the previous section.
    2. print Print all cycles detected, but do not abort execution. When cycles are present, the order of static construction is implementation defined, and not guaranteed to be valid.
    3. ignore Do not abort execution or print any cycles. When cycles are present, the order of static construction is implementation defined, and not guaranteed to be valid.
Best Practices:
  1. Avoid cyclical imports where practical. They can be an indication of poor decomposition of a program's structure into independent modules. Two modules that import each other can often be reorganized into three modules without cycles, where the third contains the declarations needed by the other two.

Order of Static Construction within a Module

Within a module, static construction occurs in the lexical order inwhich they appear.

Order of Static Destruction

This is defined to be in exactly the reverse order of static construction.Static destructors for individual modules will only be run if thecorresponding static constructor successfully completed.

Shared static destructors are executed after static destructors.

Order of Unit tests

Unit tests are run in the lexical order in which they appear within amodule.

Mixin Declaration

MixinDeclaration:mixin(ArgumentList);

EachAssignExpression in theArgumentList is evaluated at compile time, and the result must be representable as a string. The resulting strings are concatenated to form a string. The text contents of the string must be compilable as validDeclDefs, and is compiled as such.

The content of a mixin cannot be forward referenced by otherDeclDefs of the same scope because it is not yet pulled into the AST.

class B : A {}// Error: undefined identifier `A`mixin ("class A {}");

Forward references may only work in function bodies because they are processed after the declarations:

void v(){class B : A {}}mixin ("class A {}");

Package Module

A package module can be used to publicly import other modules, whileproviding a simpler import syntax. This enables the conversion of a module into a packageof modules, without breaking existing code which uses that module. Example of aset of library modules:

libweb/client.d:
module libweb.client;void runClient() { }
libweb/server.d:
module libweb.server;void runServer() { }
libweb/package.d:
module libweb;publicimport libweb.client;publicimport libweb.server;

The package module's file name must bepackage.d. The module nameis declared to be the fully qualified name of the package. Package modules canbe imported just like any other modules:

test.d:
module test;// import the package moduleimport libweb;void main(){    runClient();    runServer();}

A package module can be nested inside of a sub-package:

libweb/utils/package.d:
// must be declared as the fully qualified name of the package, not just 'utils'module libweb.utils;// publicly import modules from within the 'libweb.utils' package.publicimport libweb.utils.conv;publicimport libweb.utils.text;

The package module can then be imported with the standard module importdeclaration:

test.d:
module test;// import the package moduleimport libweb.utils;void main() { }
Grammar
Declarations
Copyright © 1999-2025 by theD Language Foundation | Page generated byDdoc on Fri Oct 10 22:16:56 2025

[8]ページ先頭

©2009-2025 Movatter.jp