Язык Nemerle.Часть 2
От: Владислав Чистяков(VladD2) Российская Империя www.nemerle.org
Дата: 10.04.10 08:19
Оценка: 970 (13) +1
Статья:
Язык Nemerle.Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.


Авторы:
Владислав Чистяков(VladD2)

Аннотация:
Эта статья продолжает цикл статей, посвященных обучению языку программирования Nemerle. Имеющиеся статьи об этом языке предполагают, что программист хорошо знаком с Microsoft .NET Framework и языком программирования C#. Данный же цикл статей, напротив, рассчитан на людей, не знакомых ни с тем, ни с другим, и может быть даже применен для изучения программирования как такового. Новичкам в программировании может потребоваться помощь людей, уже знающих программирование.

17.07.13 20:06: Перенесено из 'Nemerle'
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Язык Nemerle.Часть 2
От: Аноним  
Дата: 10.04.10 13:42
Оценка:
Ctrl+H Outut -> Output
Re: Язык Nemerle.Часть 2
От: Аноним  
Дата: 16.04.10 06:02
Оценка:
Здравствуйте, Владислав Чистяков(VladD2), Вы писали:

ВЧV>...Macroses...

Нету такого слова.
Единственое число — Macro.
Множественное — Macros.

"Macrosoes" — это как "Childrens"
Re[2]: Язык Nemerle.Часть 2
От: Shame Россия funtoo.org
Дата: 16.04.10 08:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>"Macrosoes" — это как "Childrens"


скорее как "Dogses" или "Catses" :P Переводя документацию меня иногда манило так написать
الحقيقة:الشئ الوحيد الذي(لا)يصدقه الناس!ا الزواج : جمع.وطرح.ثم(ضرب)!ولكنه قبل ذلك(قسمة) المحامي:لسان.وحنجرة.وروب!يدافع عن مال موكله (أعزائي)!وهو لا يعرف أحد منّا!الطالب (الأول)على فصله!لولا وجود الأخرين
Re: Язык Nemerle.Часть 2
От: Слава Израиль  
Дата: 16.05.10 09:31
Оценка:
Здравствуйте, Владислав Чистяков(VladD2), Вы писали:


В примере выше «fahrenheit» – это изменяемая переменная.


В слове "переменная", мне кажется, уже заложено, что сущность изменяема, поэтому понятие "изменяемая" переменная — избыточное понятие. А неизменяемая переменная — это уже не переменная. Где здесь баг — в русском языке или в языке Nemerle ?
Спасибо за внимание
Re[2]: Язык Nemerle.Часть 2
От: hardcase Пират http://nemerle.org
Дата: 16.05.10 11:01
Оценка:
Здравствуйте, Слава, Вы писали:

С>Здравствуйте, Владислав Чистяков(VladD2), Вы писали:



С>

С>В примере выше «fahrenheit» – это изменяемая переменная.


С>В слове "переменная", мне кажется, уже заложено, что сущность изменяема, поэтому понятие "изменяемая" переменная — избыточное понятие. А неизменяемая переменная — это уже не переменная. Где здесь баг — в русском языке или в языке Nemerle ?


Изначально (ML) конструкция вида "имя = значение" называется связыванием. Таким образом, можно сказать что есть изменяемое связывание (переменная) и неизменяемое (постоянная). Переменными все эти def-ы и mutable-ы называются только для того, чтобы не травмировать незнакомого с ML читателя.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Язык Nemerle.Часть 2
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.05.10 13:24
Оценка:
Здравствуйте, Слава, Вы писали:

С>В слове "переменная", мне кажется, уже заложено, что сущность изменяема, поэтому понятие "изменяемая" переменная — избыточное понятие. А неизменяемая переменная — это уже не переменная. Где здесь баг — в русском языке или в языке Nemerle ?


Здесь никаких багов нет. Переменная — это то что может получить какое-то значение во время исполнения. В Nemerle есть два типа переменных. Переменные первого типа можно задать один раз. Значение переменных второго типа можно изменять множество раз.

Вот чего нет (хотя может быть и следовало бы выделить) — это констант. Константы появляются не явно. Для их объявления нужно задать статическое неизменяемое поле с типом который может быть преобразован в константу (т.е. должен быть строкой, символом или числом).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Язык Nemerle.Часть 2
От: achp  
Дата: 13.06.10 21:41
Оценка: +1
Было бы неплохо в статье проставить ссылку на часть 1.
Re: Язык Nemerle.Часть 2
От: Real 3L0 Россия http://prikhodko.blogspot.com
Дата: 08.02.11 06:57
Оценка:
Здравствуйте, Владислав Чистяков(VladD2), Вы писали:

ВЧV>Статья:

ВЧV>Язык Nemerle.Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.


Проблема в том, что тип списка градусов Цельсия был list[int] (то есть список, хранящий элементы целочисленного типа), а список, который мы получили в результате преобразования, имеет тип list[double] (то есть хранящий элементы типа числа с плавающей точкой). Мы не можем передать функции «convert» в качестве первого параметра список типа list[double], а в качестве второго – функцию типа «double -> double» или «double -> int».


Почему сделали невозможность передачи double?
Вселенная бесконечна как вширь, так и вглубь.
Re[2]: Язык Nemerle.Часть 2
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.11 10:27
Оценка: 4 (1)
Здравствуйте, Real 3L0, Вы писали:

R3>

R3>Проблема в том, что тип списка градусов Цельсия был list[int] (то есть список, хранящий элементы целочисленного типа), а список, который мы получили в результате преобразования, имеет тип list[double] (то есть хранящий элементы типа числа с плавающей точкой). Мы не можем передать функции «convert» в качестве первого параметра список типа list[double], а в качестве второго – функцию типа «double -> double» или «double -> int».


R3>Почему сделали невозможность передачи double?


Потому что это статически типизированный язык. Типы double и int имеют разные размеры и семантику.
Вывод же типов выводит конкретные типы, а не обобщенные.

О том как сделать обобщенную функцию сказано несколькими абзацами ниже.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Язык Nemerle.Часть 2
От: Real 3L0 Россия http://prikhodko.blogspot.com
Дата: 08.02.11 10:36
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Потому что это статически типизированный язык. Типы double и int имеют разные размеры и семантику.

VD>Вывод же типов выводит конкретные типы, а не обобщенные.

Так в том и вопрос: почему бы не выводить обобщённые типы?
Или рано такие вопросы задавать?

VD>О том как сделать обобщенную функцию сказано несколькими абзацами ниже.


Это я, конечно, прочитал, перед тем как вопрос задать.
Вселенная бесконечна как вширь, так и вглубь.
Re[4]: Язык Nemerle.Часть 2
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.11 11:02
Оценка: 2 (1)
Здравствуйте, Real 3L0, Вы писали:

R3>Так в том и вопрос: почему бы не выводить обобщённые типы?


Ну, это вопрос не ко мне. Вывод типов делал Мишешь Москаль. Его алгоритм получился весьма крут, но не шустр (к сожалению), ограничен выводом конкретных типов в рамках тел методов и выводит конкретные типы.

В работе посвященной алгоритму вывода типов, в разделе "Возможные направления дальнейшего исследования", Мишель указал что можно заняться обобщением алгоритма для вывода обобщенных типов.

Практика показала, что вывода конкретных более чем достаточен для 99% случаев. Мне лично приходилось описывать обощенную локальную функцию только пару раз за 4 года. И то один раз это был пенесометрийный код, а не реальный прикладной.

Тут дело в том, что код внутри методов — это конкретный код. Он базируется на типах параметров методов параметрах типов методов и типов в которых он объявлен. По этому, если тип или метод обобщенные, то и код получается обобщенным (автоматически).

Для примеров вроде приведенного в этой части уже есть обобщенные методы, а если бы их не было, то имело бы смысл их создать. Ну, а для публичных методов в Nemerle вывода типов нет. И сделано это по двум причинам. Во-первых это резко замедлило бы компиляцию (и без того не быструю). Во-вторых это привело бы к массам непонятных ошибок с совершенно невнятной диагностикой, так как зависимости типов распространялись бы на весь проект и что-там сложилось смог бы понять только компилятор.

В таких условиях особого смысла в выводе обобщенных типов особого смысла нет. В тех редких случаях когда нужна обобщенная локальная функция (а это единственный случай когда в этом есть смысл) можно просто указать параметр типа явно. Они обычно имеют короткие имена и не засерают код.

R3>Или рано такие вопросы задавать?


Нет — это весьма разумный вопрос. Если человек его задает, значит он понял написанное. Что не может не радовать.

VD>>О том как сделать обобщенную функцию сказано несколькими абзацами ниже.


R3>Это я, конечно, прочитал, перед тем как вопрос задать.


Тогда ты должен был еще прочитать, что на самом деле такая функция уже есть, а стало быть ее реализация была нужна только в демонстрационных целях. В том числе чтобы продемонстрировать, что вывод типов производит вывод конкретного типа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Язык Nemerle.Часть 2
От: Real 3L0 Россия http://prikhodko.blogspot.com
Дата: 08.02.11 13:07
Оценка:
Здравствуйте, Владислав Чистяков(VladD2), Вы писали:

ВЧV>Статья:

ВЧV>Язык Nemerle.Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.


В статье используются два макроса: "if" и "when". "When" — это "if" без "else".
Нашел, что:

We cannot use the given macro without an "else" construct, as we can in C, since "else" is a required keyword, and it is not possible to make it non-required, because it would introduce ambiguity (after all, "if" could be used in an expression!).

Какие неоднозначности имеются в виду?
Вселенная бесконечна как вширь, так и вглубь.
Re[2]: Язык Nemerle.Часть 2
От: _nn_ www.nemerleweb.com
Дата: 08.02.11 13:14
Оценка: 4 (1)
Здравствуйте, Real 3L0, Вы писали:

R3>Здравствуйте, Владислав Чистяков(VladD2), Вы писали:


ВЧV>>Статья:

ВЧV>>Язык Nemerle.Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.


R3>В статье используются два макроса: "if" и "when". "When" — это "if" без "else".

R3>Нашел, что:
R3>

R3>We cannot use the given macro without an "else" construct, as we can in C, since "else" is a required keyword, and it is not possible to make it non-required, because it would introduce ambiguity (after all, "if" could be used in an expression!).

R3>Какие неоднозначности имеются в виду?

def x = if (true) "a" else "b";

В этом случае невозможно сделать if без else.
Каждая ветка должна что-то вернуть.

В отличии от этого, макрос when всегда возвращает void.
Соответственно это не позволяет его использовать в выражениях.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Язык Nemerle.Часть 2
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.11 16:24
Оценка:
Здравствуйте, Real 3L0, Вы писали:

R3>В статье используются два макроса: "if" и "when". "When" — это "if" без "else".

R3>Какие неоднозначности имеются в виду?

Синтаксические. Как, например, распознавать конструкцию:
if (e1) e2 if (e3) e4 else e5

В Nemerle if — это выражение, а не стэйтмент (т.е. аналогичен оператору ?: из С). По этому очень важно иметь однозначную грамматику.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Язык Nemerle.Часть 2
От: Real 3L0 Россия http://prikhodko.blogspot.com
Дата: 08.02.11 19:40
Оценка:
Здравствуйте, Владислав Чистяков(VladD2), Вы писали:

ВЧV>Статья:

ВЧV>Язык Nemerle.Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.


В качестве одного из преимуществ языка приводится то, что его легче читать.
Где-то это явно видно, но где-то — мне ещё пока трудно перестроить мышление.
Например, в статье приводится код (основной пример):
def lexer(text : string) : list[Token]
{
  mutable index = 0;
  
  def peek() : char
  {
    if (index >= text.Length) '\0' else text[index]
  }

  def read() : char
  {
    def ch = peek();
    when (index < text.Length)
      index++;
    ch
  }

  def isDigit(ch) { ch >= '0' && ch <= '9' }

  def loop(resultTokens : list[Token]) : list[Token]
  {
    def number(ch : char, accumulator : int = 0) : int
    {
      def highOrderValue    = accumulator * 10;
      def currentOrderValue = ch - '0' : int;
      def currentValue      = highOrderValue + currentOrderValue;
  
      if (isDigit(peek()))
        number(read(), currentValue);
      else
        currentValue
    }

    def error()
    {
      WriteLine(string(' ', index - 1) + "^");
      WriteLine("ожидается число или оператор");
      (Token.Error() :: resultTokens).Reverse()
    }
    
    def ch = read();

    match (ch)
    {
      | ' ' | '\t'            => loop(resultTokens) // игнорируем пробелы
      | '+' | '-' | '*' | '/' => loop(Token.Operator(ch.ToString()) :: resultTokens)
      | '\0'                  => resultTokens.Reverse()
      | _ when isDigit(ch)    => loop(Token.Number(number(ch)) :: resultTokens)
      | _                     => error()
    }
  }
  
  loop([])
}


1. Непревычно, что начало точки разбора функции, по сути, находится в самом конце. Ну, тут причина понятна, это я просто брюзжу.
2. Непревычно, что новые элементы в список resultTokens добавляются с начала, что приводит к необходимости переворачивать список. Я, конечно, понимаю, что пример специальный, но не мог бы кто-нибудь преобразовать функцию так, чтобы новые элементы в resultTokens добавлялись в конец? Если это возможно. (Не обязательно дословно точно.)
Вселенная бесконечна как вширь, так и вглубь.
Re[2]: Язык Nemerle.Часть 2
От: Ziaw Россия  
Дата: 08.02.11 21:09
Оценка: 2 (1)
Здравствуйте, Real 3L0, Вы писали:

R3>1. Непревычно, что начало точки разбора функции, по сути, находится в самом конце. Ну, тут причина понятна, это я просто брюзжу.


частое явление в функциональных языках. Напишем кучу функций, потом из вызовем.

R3>2. Непревычно, что новые элементы в список resultTokens добавляются с начала, что приводит к необходимости переворачивать список. Я, конечно, понимаю, что пример специальный, но не мог бы кто-нибудь преобразовать функцию так, чтобы новые элементы в resultTokens добавлялись в конец? Если это возможно. (Не обязательно дословно точно.)


Список в nemerle неизменяемый, поэтому, на его основе порождается еще один список с заданной головой, хвостом для которого будет являться старый список. Это очень простая операция имеющая в nemerle даже специальный оператор ::. Для добавления в хвост придется пересоздавать весь список заново, либо отказаться от иммутабельности.
Re[2]: Язык Nemerle.Часть 2
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.11 22:46
Оценка: 2 (1)
Здравствуйте, Real 3L0, Вы писали:

R3>В качестве одного из преимуществ языка приводится то, что его легче читать.

R3>Где-то это явно видно, но где-то — мне ещё пока трудно перестроить мышление.

Как часто бывает нашей жизни преимущества порождают и недостатки.

R3>1. Непревычно, что начало точки разбора функции, по сути, находится в самом конце. Ну, тут причина понятна, это я просто брюзжу.


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

Но этот недостаток нивелируется при использовании IDE. В VS локальные функции по умолчанию свернуты и тот же самый код будет выглядеть так:
def lexer(text : string) : list[Token]
{
  mutable index = 0;
  
+ def peek() : char
+ def read() : char
+ def isDigit(ch) { ch >= '0' && ch <= '9' }
+ def loop(resultTokens : list[Token]) : list[Token]
  
  loop([])
}

Для изучения конкретной функции просто нажимаем на "+" и получаем что-то вроде:
def lexer(text : string) : list[Token]
{
  mutable index = 0;
  
+ def peek() : char
+ def read() : char
+ def isDigit(ch) { ch >= '0' && ch <= '9' }

- def loop(resultTokens : list[Token]) : list[Token]
  {
+   def number(ch : char, accumulator : int = 0) : int
+   def error()
    
    def ch = read();

    match (ch)
    {
      | ' ' | '\t'            => loop(resultTokens) // игнорируем пробелы
      | '+' | '-' | '*' | '/' => loop(Token.Operator(ch.ToString()) :: resultTokens)
      | '\0'                  => resultTokens.Reverse()
      | _ when isDigit(ch)    => loop(Token.Number(number(ch)) :: resultTokens)
      | _                     => error()
    }
  }
  
  loop([])
}

и так далее.

R3>2. Непревычно, что новые элементы в список resultTokens добавляются с начала, что приводит к необходимости переворачивать список. Я, конечно, понимаю, что пример специальный, но не мог бы кто-нибудь преобразовать функцию так, чтобы новые элементы в resultTokens добавлялись в конец? Если это возможно. (Не обязательно дословно точно.)


Это уже особенность не языка, а структуры данных list[T]. Она так же вела бы себя и в любом другом языке. Все без исключения ФЯ имеют подобную структуру данных. Ее главная особенность — она неизменяемая. Однажды создав список они останется таковым до того момента когда GC его соберет за ненадобностью. А в функциональном коде неизменяемость — это большое достоинство. Кроме того неизменяемость позволяет порождать из одного списка другой не создавая его копии.
Следующим достоинством является константное (О(1)) время вставки.
Но все это возможно только в следствии того, что список строится от хвоста к голове.
Очень часто это даже является преимуществом. Но при сборке списка его приходится разворачивать.
В большинстве случаев это не является проблемой. К тому же зачастую список обрабатывается не по одному разу и он сам собой разворачивается. А иногда вообще не важен порядок элементов.

Ну, и в конце концов никто не запрещает использовать и другие типы данных. Например System.Collections.Generic.List[T].
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.