Похоже, что нет простого способа предотвратить то, что операторы импорта D затуманивают глобальное пространство имен:

module x;    
import std.stdio;

void main() {
    writeln("Hello!");
}

Как только вы import std.stdio, writeln становится глобальным. Исходя из [language with namespaces], было бы неплохо, если бы я мог ссылаться только на std.stdio.writeln, тем более что через неделю или две я могу легко определить, что обеспечивает writeln.

После прочтения пространств имен с классами и структурами? мне кажется, что это должно делать то, что я хочу (столь же громоздко, как это):

module x;
import std.stdio;

class String {
  struct write {
    auto println = writeln;
  }
}

void main() {
  String string = new String();
  string.write.println("Hello!");
}

Но я получаю Error: variable [...] type void is inferred from initialiser [...], and variables cannot be of type void, что означает отсутствие псевдонима функций.

Если бы я писал C, я мог бы понять отсутствие пространств имен (но я все еще мог бы достичь их с помощью структур и точечной нотации). Есть ли способ сделать так, чтобы импортированные имена не были такими глобальными?

2
cat 27 Фев 2016 в 23:29

4 ответа

Лучший ответ

Я склонен согласиться с @weltensturm - D изящно обрабатывает конфликты, и искусственное создание пространств имен может только запутать ситуацию.

Одна из приятных частей D (ИМХО) - избегать тех длинных имен, которые вы видите в других языках, не беспокоясь о том, что произойдет что-то ужасное.

Однако, если вам действительно нужно, взгляните на документацию на модули, в которых показано, как переименовать модуль:

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
}

Вы также можете использовать статический импорт, поэтому вы будете вынуждены использовать полное имя:

static import std.stdio;

void main()
{
    std.stdio.writeln("hello!"); // OK
    writeln("hello!");           // error, writeln is undefined
}
7
rcorre 27 Фев 2016 в 22:55

Проблема с вашим примером заключается в том, что вы вызываете Writeln, не принимая его указатель. Попробуйте &writeln. Вы также должны объявить его как static, чтобы вам не пришлось создавать экземпляр пространства имен. (Класс только со статическими функциями в D действует почти как пространство имен). Но вам следует избегать искусственного создания пространств имен, поскольку D очень хорошо справляется с конфликтами, и это только увеличит необходимую типизацию.

Что касается системы импорта D: каждое имя в импортированном модуле доступно в текущем. Но как только вы импортируете модуль с конфликтующими именами, вы все равно будете вынуждены использовать полное имя.

4
weltensturm 27 Фев 2016 в 20:56

Это довольно просто - если вам не нравится загрязнение пространства имен, вы должны выполнить статический импорт .

Вот что говорится в спецификации D (http://dlang.org/spec/module.html, раздел «Статический импорт»):

Базовый импорт хорошо работает для программ с относительно небольшим количеством модулей и импорта. Если импортируется много, могут начаться конфликты имен между именами в различных импортированных модулях. Один из способов остановить это - использовать статический импорт. Статический импорт требует использования полного имени для ссылки на имена модуля:

Примере:

static import std.stdio;

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

Если моему коду требуется только один или два символа из модуля, я использую выборочный импорт, как упомянул Макс Алибаев. Скажем, я буду часто использовать Writeln (). - Тогда у меня, скорее всего, будет строка import std.stdio : writeln; в моем коде D.

5
DejanLekic 27 Фев 2016 в 22:57

Вы ищете Выборочный импорт (его можно найти на http://dlang.org /spec/module.html)?

import std.stdio : writeln;
4
Max Alibaev 27 Фев 2016 в 20:42