html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Voldemort типы в D tutorial

Данный пост расскажет об уникальной фишке D — Voldemort типы. Типы, которые можно использовать, но нельзя назвать. Данное название не очень подходит им, но Walter Bright очень любит так их называть. Voldemort типы очень часто встречаются в стандартной библиотеке Phobos, особенно в модулях std.algorithm и std.array. Осваивающие D могут часами штудировать документацию в поисках типа, возвращаемого из splitter или joiner, а возвращают они именно Voldemort типы. После этого поста можно смело открывать исходники std.algorithm, ибо никакие Сами-Знаете-Кто вам будут не страшны.

Он самый

Иногда, взаимодействие существующих возможностей может привести к неожиданным сюрпризам. Мне нравится считать, что мы изначально заложили Voldemort типы в D, но на самом деле они были найдены Андреем Александреску. Что это за Voldermort типы? Читайте дальше.



Во-первых, немного вводной информации. Для понимания материала необходимо иметь представление о Ranges. В первом приближении, они были придуманы как замена итераторам и очень схожи с подходом C# с его интерфейсом IEnumerable. В языке D любой тип, реализующий следующие методы, будет представлять из себя InputRange:
front - get the first element of the range
popFront - remove the first element of the range
empty - are there more elements in the range?


Эти методы реализуют основу для итерации по типу. Теперь just fo fun, давайте спроектируем InputRange, который вернет бесконечную последовательность случайных чисел. (Мы также называем такие функции генераторами.)

Он может выглядеть так (не очень хороший генератор случайных чисел, но скоро им станет):
module rnd;
 
struct RandomNumberGenerator {
 
    this(uint seed) {
        next = seed;
    popFront();  // get it going
    }
 
    @property int front() {
    return ((next / 0x10000) * next) >> 16;
    }
 
    void popFront() {
    next = next * 1103515245 + 12345;
    }
 
    @property bool empty() { return false; }
 
  private:
    uint next;
  }


И функция, которая вернет его:
RandomNumberGenerator generator(uint seed) {
  return RandomNumberGenerator(seed);
}


И прекрасная программа, которая напечатает 10 таких чисел:
import std.stdio;
import rnd;
 
void main() {
  int count;
  foreach (n; generator(5)) {
      writeln(n);
      if (++count == 10)
      break;
  }
}


На этом обычно все и останавливаются. Но здесь есть несколько раздражающих моментов. В идеале я должен знать только о функции rnd.generator, но в модуле находится тип RandomNumberGenerator, который может существовать сам по себе. Это выглядит как нарушение инкапсуляции, так как он просачивается наружу из моей абстракции генератора.

Я бы мог отметить его атрибутом private и другие модули, кроме rnd, не смогли бы получить к нему доступ. Но этот тип все еще здесь, вне зоны, которой он принадлежит, и другие члены модуля все еще могут обращаться к нему, запривачен он или нет (в D private объявления не спрятаны от других объявлений внутри одного модуля).

Перейдем теперь к более веселым вещам. Сперва, D поддерживает вывод типов для объявлений, поэтому я могу написать так:
auto g = RandomNumberGenerator(seed);


И g будет автоматически присвоен тип RandomNumberGenerator. Это стандартная вещь. Подергав эту ниточку еще немного, и мы можем выводить возвращаемые из функций типы:
auto square(double d) {
  return d * d;
}
 
auto x = square(2.3);


И компилятор поймет, что функция square вернет double, так как это тип выражения после return. И конечно, переменная x также будет типа double. Теперь давайте перепишем нашу функцию для генератора таким образом:
module rnd;
 
auto generator(uint seed) {
 
  struct RandomNumberGenerator {
 
  @property int front() {
      return ((seed / 0x10000) * seed) >> 16;
  }
 
  void popFront() {
      seed = seed * 1103515245 + 12345;
  }
 
  @property bool empty() { return false; }
  }
 
  RandomNumberGenerator g;
  g.popFront();    // get it going
  return g;
}


Произошло что-то обворожительное. RandomNumberGenerator стал типом, который находится внутри области функции generator. Его просто не видно вне функции. Также он не может быть назван — это и есть Voldemort тип.

Мы можем только получить экземпляр этого типа:
auto g = generator(5);


И дальше использовать g. Я знаю о чем вы думаете — использовать typeof и создать другой экземпляр RandomNumberGenerator:
auto g = generator(4);
typeof(g) h;


Sorry, это не сработает, компилятор не позволит объявить Voldermort тип вне его области видимости (техническая причина — нет доступа к локальной переменной seed).

Теперь осталась только одна деталь, которая меня раздражает, цикл:
int count;
foreach (n; generator(5)) {
    writeln(n);
    if (++count == 10)
    break;
}


Он выглядит так старомодно. С помощью ranges, мы можем обойтись без толстого цикла, и вместо него использовать range take , чтобы просто взять первые 10 элементов этого range:
void main() {
  foreach (n; take(generator(5), 10))
  writeln(n);
}


И дальше использовать writeln, чтобы совсем избавиться от цикла:
void main() {
  writeln(take(generator(5), 10));
}


Являются ли Voldemort типы действительно только existential типами?


Дан тип T, и тип U, который может быть извлечен из T и который состоит в определенном отношении c T, является existential типом.

Для примера, если у нас есть тип T, являющийся указателем, мы можем вывести из него базовый existential тип U с помощью:
import std.stdio;
 
void extractU(T)(T t) {
  static if (is(T U : U*))
    writefln("type %s is a pointer to an %s", typeid(T), typeid(U));
  else
    writefln("type %s is not a pointer", typeid(T));
}
 
void main() {
  int* t;
  extractU(t);
  double d;
  extractU(d);
}


Что выведет на экран:
type int* is a pointer to an int
type double is not a pointer


В то время как Voldemort типы безусловно прячут свою реализацию, это, однако, не делает их existential типами. Так как Voldemort типы не могут быть получены из некого über типа, они не являются existential.

Заключение

Voldemort типы стали замечательным открытием в D, что позволило инкапсулировать типы так, что их можно использовать, но нельзя назвать.

Источник: Walter Whight Voldemort Types In D
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

6

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции