Простые имена не так уж просты. Часть 2.

А также о вулканах и еде

Я вернулся из короткого отпуска – навещал друзей на острове Мауи. Я никогда раньше не был в этой части света. Как выяснилось, это небольшой островок посреди Тихого океана, который просто напичкан вулканами (который состоит из одних вулканов). Жутко! Но потрясающе!

Самое большое впечатление Гавайские острова произвели на меня, совершенно очевидными даже для моего нетренированного глаза, геомеханическими и водными процессами, создавшими их ландшафт. Горы, кратеры, долины рек, пляжи с красным песком, легкоразрушаемые скалы, все это сильно отличалось от более древних горных пейзажей (кстати, также частично вулканического происхождения) среди которых я жил последние десять лет.

Также мне доставило немало удовольствия изучение произношения и чтения гавайских названий.Если понять основные принципы, то все оказывается вполне логичным; вскоре я мог с легкостью напевать следующие названия: НАЦИОНАЛЬНЫЙ ПАРК WAINAPANAPA – ва-и-а-напа-напа, или ПРОСПЕКТ PUUNENE – пу-ээ-нэй-нэй, или УЛИЦА MAILIBEHANAMONOTANA – «Майли-Стюарт-на-самом-деле-Ханна-Монтана».

Огромная благодарность Кею, Ар и Ди, которые будили меня с Леей всю неделю; если вы собираетесь на Гавайи – я очень рекомендую, если конечно получиться, пожить с местными, особенно если попадутся классные ребята. А на Мауи все жители просто потрясающие, за исключением рейнджеров из Национального Парка Ваиапанапа (просто прекрасного даже для Мауи), которые угрюмы по определению. Как сказал один из гавайцев, представитель туристического бизнеса, «У них нет особой доброжелательности (the big aloha) »

Самая забавная встреча произошла на шоссе Хана. На пути встречается множество маленьких остановок, на которых кто-то поставил шалаш или просто припарковал трейлер и продает кокосы, фруктовые коктейли, банановый хлеб и т.д. Сделанные вручную вывески, невероятной красоты природа, глушь, я думаю, вы уже представили себе картину. Возле одной такой остановки стоял молодой парень, где-то за двадцать, и продавал жареную еду. В основном это была обыкновенная китайская еда в американском стиле, но была и французская выпечка, рыба с жареным картофелем и много чего еще. Английский для этого парня явно был не родным, говорил он с сильным акцентом, но понять его было можно. Мы стояли в очереди позади женщины средних лет, которая говорила с типичным американским акцентом жителей среднего запада. Беседа была примерно такая:

Она: Я не очень хочу кушать, поэтому можно мне рыбу без картошки?

Он (не вполне понимая): Половина порции?

Она (громче): Сколько будет стоить без картошки?

Эта перепалка продолжалась некоторое время, непонимание раздражало собеседников все больше и больше, пока женщина не выпалила совсем громко:

- Могу я поговорить с вашим менеджером?

Лея, Кей и я оказались просто в ступоре, по-другому не скажешь. Откуда, черт возьми, по ее мнению, здесь мог появиться менеджер? Перед ней был прилавок, за которым находился трейлер с продуктами, за которым находились джунгли, за которыми были зубристые вулканические скалы, сразу за которыми был Тихий Океан. И какой же тип структуры управления нужен по ее мнению для управления одним парнем, который продает на обочине рис с печеными ананасами? Мое заключение: у людей бывают весьма странные представления. Иногда их убеждения приводят к тому, что они уходят раздраженными без рыбы и без картошки, даже когда приличное количество рыбы и чипсов предлагают за вполне разумную цену. Я надеюсь, в Ганне ей повезло больше.

Итак, хватит путешествий. Давайте вспомним последнюю задачку: корректный код, который без проблем компилируется. Я был весьма удивлен, когда впервые понял, в чем дело. Складывается впечатление, что этот код нарушает правило о запрете использования одинаковых простых имен с неоднозначным значением в одном блоке.

Ключ к пониманию того, почему этот код корректен, лежит в том, что конструкции запросов (query comprehensions) и циклы foreach – это всего лишь синтаксический сахар для другой программы, и именно эту программу нужно анализировать на корректность. Наша исходная программа, которая выглядит так:

static void Main()
{
  int[] data = { 1, 2, 3, 1, 2, 1 };
  foreach (var m in from m in data orderby m select m)
    System.Console.Write(m);
}

преобразуется в:

static void Main()
{
  int[] data = { 1, 2, 3, 1, 2, 1 };
  {
    IEnumerator<int> e = ((IEnumerable<int>)(data.OrderBy(m=>m)).GetEnumerator();
    try
    {
      int m;
      while(e.MoveNext())
      {
        m = (int)(int)e.Current;
        Console.Write(m);
      }
    }
    finally
    {
      if (e != null) ((IDisposable)e).Dispose();
    }
  }
}

В преобразованной программе m используется в пяти местах:

1) в объявлении формального параметра лямбда-выражения;

2) в теле лямбда-выражения (в качестве формального параметра);

3) в объявлении локальной переменной;

4) запись в цикле (в качестве локальной переменной);

5) чтение в цикле (в качестве локальной переменной).

Существует ли использование локальной переменной до ее объявления? Нет.

Существует ли два объявления с одинаковыми именами в одной и той же области объявлений (declaration space)? Может показаться что да. Тело функции Main определяет область объявлений для локальных переменных и совершенно очевидно, что тело метода Main неявно содержит два объявления m – одно как параметр лямбда-выражения и второе – как локальная переменная. Но как я уже упоминал, для области объявлений локальных переменных существуют специальные правила определения перекрытий (overlaps). Область объявлений локальных переменных не может содержать объявление с именем, которое будет совпадать с именем, объявленным во вложенной области объявлений. Но не является ошибкой внешняя область объявлений, содержащая два косвенных объявления. Поэтому в этом случае ответ – нет, не существует области объявлений локальных переменных, с явным объявлением m, которое бы содержало вложенную область объявлений с еще одним явным объявлением m. В нашем случае две области объявлений, с явным объявлением m, не пересекаются.

Существует ли область объявления, которая содержит два неоднозначных использования имени m? Ответ опять: да. Внешний блок функции Main содержит два неоднозначных использования m. Но опять же, это не важно. Вопрос в том, существует ли такая область объявлений, с явным объявлением m, использование m в которой было бы неоднозначным. Опять же, никакой проблемы нет, потому что у нас есть две области объявлений, но они друг с другом не пересекаются.

Этот код корректным делает одна весьма интересная особенность – объявление в сгенерированном коде переменной цикла внутри блока try. Если бы эта переменная была объявлена вне блока try, это бы привело к нарушению правила непротиворечивого использования простых имен в областях объявления.

Оригинальное сообщение: Simple names are not so simple, Part Two, plus, volcanoes and fried foods