Nemerle coding style
От: _nn_ www.nemerleweb.com
Дата: 24.11.09 22:05
Оценка:
Сообственно у Nemerle пока нет документа, который бы описывал как принято писать код.
Может стоит начать обсуждение здесь и таким образом сформировать документ ?

Отталкиваться можно от стиля RSDN на C#, например, и добавлять необходимые изменения по мере обсуждения.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Nemerle coding style
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 25.11.09 00:41
Оценка:
Я следую стандарту RSDN. Необходимых изменений даже, как-то сразу на ум не приходит.
Ce n'est que pour vous dire ce que je vous dis.
Re[2]: Nemerle coding style
От: _nn_ www.nemerleweb.com
Дата: 25.11.09 11:14
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Я следую стандарту RSDN. Необходимых изменений даже, как-то сразу на ум не приходит.


Ну к примеру как лучше писать match?

1.
match(a)
{
  | h :: t => ...
  | h :: [] => ...
  | _ => ...
}


2.
match(a)
{
| h :: t => ...
| h :: [] => ...
| _ => ...
}


3.
match(a)
{ | h :: t => ...
  | h :: [] => ...
  | _ => ...
}


Использование match в функции.
Использовать явно или неявно ?

1.
def f(a)
{
  | h :: t => ...
  | h :: [] => ...
  | _ => ...
}


2.
def f(a)
{
  match(a)
  {
    | h :: t => ...
    | h :: [] => ...
    | _ => ...
  }
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 16:25
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Сообственно у Nemerle пока нет документа, который бы описывал как принято писать код.

__>Может стоит начать обсуждение здесь и таким образом сформировать документ ?

Кое что есть, но оно на сайте, а но лежит.

__>Отталкиваться можно от стиля RSDN на C#, например, и добавлять необходимые изменения по мере обсуждения.


Во многом стиль кодирования шарпа не применим для немерле. Скажывается функциональная природа и особенности языка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 16:29
Оценка: +1
Здравствуйте, Don Reba, Вы писали:

DR>Я следую стандарту RSDN. Необходимых изменений даже, как-то сразу на ум не приходит.


На самом дела слепое следование стандартам для шарпа приводит к некоторым проблемам.

1. Функциональный код часто лучше оставить на одной строке нежели резать на строки (без переменных). Особенно это отчетливо видно на операторе match.
2. Многие конструкции вроде if/else хотя и похожи на шарповские, но отличаются от них.
3. Отсутствие return так же делает код другим.
4. Есть конструкции не имеющие аналогов в шарпе. Для них вообще нет правил форматирования (опять же match).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 16:31
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Ну к примеру как лучше писать match?


__>1.

__>
__>match(a)
__>{
__>  | h :: t => ...
__>  | h :: [] => ...
__>  | _ => ...
__>}
__>


__>2.

__>
__>match(a)
__>{
__>| h :: t => ...
__>| h :: [] => ...
__>| _ => ...
__>}
__>


__>3.

__>
__>match(a)
__>{ | h :: t => ...
__>  | h :: [] => ...
__>  | _ => ...
__>}
__>



4.
match(a) {
  | h :: t => ...
  | h :: [] => ...
  | _ => ...
}


5.
match(a) { | h :: t => ... | h :: [] => ... | _ => ... }
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle coding style
От: Aleх  
Дата: 25.11.09 16:45
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Я следую стандарту RSDN. Необходимых изменений даже, как-то сразу на ум не приходит.

В исходниках самого компилятора NCC нет четкого стиля форматирования кода.

В одном и том же файле используются разные стили расставления скобок:
 // assembly attribute
    eat_assembly_attributes (tok : Token.LooseGroup) : void {
      match (tok.Child) {
        | ...            
        | _ => ()
      }
    }

 parse_accessor_body (p : list [PParameter], implemented : list [PExpr]) : list [PExpr] * FunBody
    {
      match (peek_token ())
      {
        ...
      };
    }

И именование методов:
ParseTypeDeclaration (toks : Token) : TopDeclaration
    {
...
    }

Ну и ещё, не удобно то, что отступы в начале строк делаются пробелами. Для этого всё-таки есть табы. Но поскольку для некоторых это холиварная тема, наверное стоит сделать автоматическое форматирование кода кнопкой в редакторе.

Не понятно насчет точек с запятыми, они расставлены абсолютно рандомно: после match'а нужна точка с запятой?
Re[3]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 17:21
Оценка:
Здравствуйте, Aleх, Вы писали:

A>после match'а нужна точка с запятой?


match — это оператор. Он может быть как отдельным выражением и тогда после него нужна точка с запятой, если есть идущие следом выражения. Так же он может встречаться в выражениях как подвыражение. Тогда после него просто нельзя ставить точку с запятой.

Что до стиля внутри компилятора, то можно скзать, что в нем действительно смешение стилей. Я к этому приложил свою руку.

На мой взгляд некоторые аспекты стиля форматирования выбранные первыми авторами языка неудобны.

Посему лично я объединил принципы форматирования выработанные в рамках РСДН (описаны на нашем сайте) и принципы специфичные для Немерле.

Могу чуть позже описать стандарт форматирования которого я придерживаюсь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Nemerle coding style
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 25.11.09 17:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>На самом дела слепое следование стандартам для шарпа приводит к некоторым проблемам.


Ну, это само собой.

VD>1. Функциональный код часто лучше оставить на одной строке нежели резать на строки (без переменных). Особенно это отчетливо видно на операторе match.

VD>2. Многие конструкции вроде if/else хотя и похожи на шарповские, но отличаются от них.
VD>3. Отсутствие return так же делает код другим.
VD>4. Есть конструкции не имеющие аналогов в шарпе. Для них вообще нет правил форматирования (опять же match).

Для match один к одному подходят рекомендации для switch/case. Разве нет?

match с длинными последовательностями в case:

match (condition) 
{
    | 1
    | 2 =>
        x = ...;
    | 3 =>
        x = ...;
    | _ =>
        x = ...;
}


match с короткими последовательностями в case:

match (condition) 
{
    | 1 => x = 1;
    | 2 => x = 2;
    | 3 => x = 3;
    | _ => x = 100;
}

Ce n'est que pour vous dire ce que je vous dis.
Re[3]: Nemerle coding style
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 25.11.09 17:56
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Здравствуйте, Don Reba, Вы писали:


DR>>Я следую стандарту RSDN. Необходимых изменений даже, как-то сразу на ум не приходит.


__>Ну к примеру как лучше писать match?


Придерживаюсь первого варианта, аналогично использованию switch:

__>1.

__>
__>match(a)
__>{
__>  | h :: t => ...
__>  | h :: [] => ...
__>  | _ => ...
__>}
__>


__>Использование match в функции.

__>Использовать явно или неявно ?

А это действительно не определить по стандарту RSDN. Я предпочитаю неявную запись.

__>1.

__>
__>def f(a)
__>{
__>  | h :: t => ...
__>  | h :: [] => ...
__>  | _ => ...
__>}
__>
Ce n'est que pour vous dire ce que je vous dis.
Re[4]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 19:36
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Для match один к одному подходят рекомендации для switch/case. Разве нет?


Нет. Во-первых, как правильно заметил _nn_ есть многие норовят не отбивать | а оставлять его на уровне открывающей фигурной скобкой. Во-вторых, первый | можно опускать. В-третьих, есть случаи (и они часты) когда выражения влезают в ту же строку где находится =>. В-четвертных, в match нет break и если не отбивать выражения перенесенные на следующую строку пустой строкой, то оно сливается со следующим паттерном.
В общем, есть много нюансов.


DR>match с короткими последовательностями в case:


DR>
DR>match (condition) 
DR>{
DR>    | 1 => x = 1;
DR>    | 2 => x = 2;
DR>    | 3 => x = 3;
DR>    | _ => x = 100;
DR>}
DR>


Дык, а этого нет в (если я не ошибаюсь) в правилах для шарпа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Nemerle coding style
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 25.11.09 20:44
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Нет. Во-первых, как правильно заметил _nn_ есть многие норовят не отбивать | а оставлять его на уровне открывающей фигурной скобкой.


Многие норовят и case не отбивать. В этом match не отличается.

VD>Во-вторых, первый | можно опускать.


Вот это уникально. ИМХО, имеет смысл только когда весь match записывается в одну строчку.

VD>В-третьих, есть случаи (и они часты) когда выражения влезают в ту же строку где находится =>.


Для этого есть рекомендация для "коротких последовательностей". Тут match тоже не отличается от switch.

VD>В-четвертных, в match нет break и если не отбивать выражения перенесенные на следующую строку пустой строкой, то оно сливается со следующим паттерном.


У выражения же отступ больше чем у образца. Как они могут слиться?
Ce n'est que pour vous dire ce que je vous dis.
Re[6]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 25.11.09 21:40
Оценка:
Здравствуйте, Don Reba, Вы писали:

DR>Многие норовят и case не отбивать. В этом match не отличается.


ОК.

DR>Вот это уникально. ИМХО, имеет смысл только когда весь match записывается в одну строчку.


По-моему, это вообще надо бы выбросить чтобы лишних вопросов не было.

DR>Для этого есть рекомендация для "коротких последовательностей". Тут match тоже не отличается от switch.


По-моему в switch не разрешалось никаких коротких последовательностей. Хотя лично я от этого сам много раз отходил.

VD>>В-четвертных, в match нет break и если не отбивать выражения перенесенные на следующую строку пустой строкой, то оно сливается со следующим паттерном.


DR>У выражения же отступ больше чем у образца. Как они могут слиться?


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

Это вообще все конечно вкусощина. Но когда приходится анализировать много ЧУЖОГО кода, то эта вкусовщина начинает становиться очень болезненной.

Чтобы разобраться в коде компилятора я не раз был вынужден переформатировать код.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Nemerle coding style
От: Аноним  
Дата: 26.11.09 05:02
Оценка: +1 :)
Здравствуйте, _nn_, Вы писали:

__>Сообственно у Nemerle пока нет документа, который бы описывал как принято писать код.

__>Может стоит начать обсуждение здесь и таким образом сформировать документ ?

__>Отталкиваться можно от стиля RSDN на C#, например, и добавлять необходимые изменения по мере обсуждения.


В Nemerle есть #pragma indent. Если она написана правильно — это и должен быть Nemerle coding style...
Re[2]: Nemerle coding style
От: _nn_ www.nemerleweb.com
Дата: 26.11.09 07:50
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, _nn_, Вы писали:


__>>Сообственно у Nemerle пока нет документа, который бы описывал как принято писать код.

__>>Может стоит начать обсуждение здесь и таким образом сформировать документ ?

__>>Отталкиваться можно от стиля RSDN на C#, например, и добавлять необходимые изменения по мере обсуждения.


А>В Nemerle есть #pragma indent. Если она написана правильно — это и должен быть Nemerle coding style...


Что значит написана правильно ?
Т.е. вы только за #pragma indent как основого стиля ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Nemerle coding style
От: _nn_ www.nemerleweb.com
Дата: 26.11.09 07:51
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Don Reba, Вы писали:


DR>>Многие норовят и case не отбивать. В этом match не отличается.


VD>ОК.


DR>>Вот это уникально. ИМХО, имеет смысл только когда весь match записывается в одну строчку.


VD>По-моему, это вообще надо бы выбросить чтобы лишних вопросов не было.

+1

Может стоит сейчас запретить пропускать первый | в match ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Nemerle coding style
От: Аноним  
Дата: 26.11.09 08:56
Оценка:
Здравствуйте, _nn_, Вы писали:

А>>В Nemerle есть #pragma indent. Если она написана правильно — это и должен быть Nemerle coding style...


__>Что значит написана правильно ?

__>Т.е. вы только за #pragma indent как основого стиля ?

Она задумана как в питоне — неправильно отформатировал — не скомпилится, так что стиль отступов предопределен.
Re[4]: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.11.09 13:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Она задумана как в питоне — неправильно отформатировал — не скомпилится, так что стиль отступов предопределен.


Ага. Читать только такой вариант не каждый может.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Nemerle coding style
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.11.09 20:29
Оценка: 11 (2)
Здравствуйте, _nn_, Вы писали:

Описывать подробно весь стиль кодирования в лом, так что я приведу пример кода и дам коментарии.

using System;
using System.Console;
using Nemerle.Utility;

[Record]
variant Token // имена типов ПаскальКейс, как в РСДН
{
  | Number   { value : int; } // если описание полей варианта влезает в одну строку
  | Operator
    {
      name  : string; // если не влезает, то каждое поле (и другие члены) на отдельной строке
    }
  | OpenBrace // пустых строк между вхождениями нет.
  | CloseBrace
  | Eof
  | Error
  
  public StartPos : int;
  
  #region object  Members
  
  public override ToString() : string
  {
    match (this) // пробел между именем оператора и скобками (как в РСДН)
    { // каждое вхождение отбито на одну табуляцию
      | Number(value)  => $"$value" // по возможности используется табличное форматирвоание
      | Operator(name) => $"$name"
      | OpenBrace      => "("
      | CloseBrace     => ")"
      | Eof            => "."
      | Error          => "Error"
    }
  }
  
  #endregion object  Members
  
}

module Program
{
  Main() : void // используются алиасы типов, а не полные имена вроде System.Void
  {
    def calc(text : string) // имена локальных функций и переменных в кэмелКэйсе
    {
      def lexer(text : string) : list[Token] // типы у локальных функций указываю только когда это помогает понят суть функции
      {
        mutable index = 0;
        
        def peek()
        {
          if (index >= text.Length) '\0' else text[index];
        } // пустых строк между описаниями локальных функций нет
        def read()
        {
          def ch = peek(); // переменные желательно отбивать от остального кода одной строкой (не строгое правило)

          when (index < text.Length)
            index++; // выражение внутри макры "when" всегда на новой строке и всегда заканчивается ";"
          ch
        }
        def isDigit(ch) { ch >= '0' && ch <= '9' } // мелкие функции можно описывать инлайном
        def number(ch : char, accumulator : int = 0) : int
        { // опять же табличное форматирование, где одно улучшает читаемость.
          def highOrderValue    = accumulator * 10; // если переменные повышают читабельность, то разносим 
          def currentOrderValue = ch - '0' : int;   // выражение на несколько строк и для его частей вводим перепменные
          def currentValue      = highOrderValue + currentOrderValue;
          
          if (isDigit(peek())) // если ветка if-а - это одно выражение, то не в коем случае не используем { и } !
            number(read(), currentValue) // если значение выражения является возвращаемым значением функции, то ";" не ставим!
          else
            currentValue
        }
        
        def loop(res : list[Token]) : list[Token]
        { // все открывающие скобки, кроем тел лябд и именованных блоков, начинаются с новой стоки
          def ch = read();

          match (ch)
          {
            | '('                   => loop(Token.OpenBrace(index)  :: res)
            | ')'                   => loop(Token.CloseBrace(index) :: res)
            | ' ' | '\t'            => loop(res) // игнорируем пробелы
            | '+' | '-' | '*' | '/' => loop(Token.Operator(index, ch.ToString()) :: res)
            | '\0'                  => res.Reverse()
            | _ when isDigit(ch)    => loop(Token.Number(index, number(ch)) :: res)
            | _ => // если вхождение match-а не влазит в одну строку, то...
              // переносим все выражения на следующую строку и начинаем их с отбивкой в одну табуляцию от "|" (начала паттерна)
              WriteLine(string(' ', index - 1) + "^");
              WriteLine($"ожидается число или оператр (в позиции $index)");
              (Token.Error(index) :: res).Reverse() // опять же возвращаемое значение не заканчивается ";"
          }
        }
        
        loop([])
      }
      
      def parseAndEval(tokens : list[Token])
      {
        def eof = Token.Eof(if (tokens.IsEmpty) 1 else tokens.Last.StartPos + 1);
        mutable current = tokens;
        
        def peek()
        {
          match (current)
          {
            | null      => Token.Error(1)
            | head :: _ => head
            | []        => eof
          }
        }
        def read()
        {
          match (current)
          {
            | null         => Token.Error(1)
            | head :: tail => 
              current = tail;
              head // если во вхожднеии более одной строки и ниже есть еще вхождения, то отделяем ее пустой строкой
              
            | []           => eof
          }
        }
        def error(token : Token, message : string) : int
        {
          WriteLine(string(' ', token.StartPos - 1) + "^");
          WriteLine(message);
          current = null;
          0
        }

        // SimpleExpr = Number | '-' SimpleExpr | '(' SumOrSub ')'
        // MulOrDive  = SimpleExpr (('*' | '/') SimpleExpr)*
        // SumOrSub   = MulOrDive  (('+' | '-') MulOrDive)*
        
        def parseSimpleExpr() : int
        {
          def tok = read();

          match (tok)
          {
            | Error         => 0
            | Operator("-") => - parseSimpleExpr()
            | Number(val)   => val
            | OpenBrace     => 
              def value = parseSumOrSub();
              def toc2  = read();

              if (toc2 is Token.CloseBrace || toc2 is Token.Error)
                value
              else
                error(tok, "Не закрытая скобка!")
            
            | _          => error(tok, "Ожидается число, унарный '-' или '('")
          }
        }        
        and parseMulOrDive() : int
        {
          def loop(firstValue)
          {
            def tok = peek();
            
            match (tok)
            {
              | Operator("*") => 
                _ = read();
                def secondValue = parseSimpleExpr();
                loop(firstValue * secondValue)

              | Operator("/") => 
                _ = read();
                def secondValue = parseSimpleExpr();
                if (secondValue == 0)
                  error(tok, "Делитель не должен быть нулем!")
                else
                  loop(firstValue / secondValue)
                  
                
              | _ => firstValue
            }
          }
          
          loop(parseSimpleExpr())
        }
        and parseSumOrSub() : int
        {
          def loop(firstValue)
          {
            def tok = peek();

            match (tok)
            {
              | Operator("+") => 
                _ = read();
                def secondValue = parseMulOrDive();
                loop(firstValue + secondValue)

              | Operator("-") => 
                _ = read();
                def secondValue = parseMulOrDive();
                loop(firstValue - secondValue)
                
              | Number | OpenBrace   => error(tok, "Ожидается оператор или конец выражения")
              | _ => firstValue
            }
          }
          
          def firstValue = parseMulOrDive();

          loop(firstValue)
        }
        
        def parse() : int
        {
          def value = parseSumOrSub();
          def tok = peek();
          
          when (!(tok is Token.Eof) && !(tok is Token.Error))
            _ = error(peek(), $"Не ожидаемый токен '$(peek())'");
            
          value
        }
        
        def res = parse();
        when (current != null)
        {
          WriteLine("Результат:");
          WriteLine(res);
        }
      }
      
      def res = lexer(text);

      unless (res.IsEmpty || res.Last is Token.Error)
        parseAndEval(res);
    }
    
    def readInput()
    {
      def res = ReadLine();
      
      unless (res == "")
      {
        calc(res);
        readInput();
      }
    }
    
    readInput();
  }
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Nemerle coding style
От: _nn_ www.nemerleweb.com
Дата: 01.12.09 08:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, _nn_, Вы писали:


VD>Описывать подробно весь стиль кодирования в лом, так что я приведу пример кода и дам коментарии.


VD>
VD>using System;
VD>using System.Console;
VD>using Nemerle.Utility;

VD>[Record]
VD>variant Token // имена типов ПаскальКейс, как в РСДН
VD>{
VD>  | Number   { value : int; } // если описание полей варианта влезает в одну строку
VD>  | Operator
VD>    {
VD>      name  : string; // если не влезает, то каждое поле (и другие члены) на отдельной строке
VD>    }
VD>  | OpenBrace // пустых строк между вхождениями нет.
VD>  | CloseBrace
VD>  | Eof
VD>  | Error
  
VD>  public StartPos : int;
  
VD>  #region object  Members
  
VD>  public override ToString() : string
VD>  {
VD>    match (this) // пробел между именем оператора и скобками (как в РСДН)
VD>    { // каждое вхождение отбито на одну табуляцию
VD>      | Number(value)  => $"$value" // по возможности используется табличное форматирвоание
VD>      | Operator(name) => $"$name"
VD>      | OpenBrace      => "("
VD>      | CloseBrace     => ")"
VD>      | Eof            => "."
VD>      | Error          => "Error"
VD>    }
VD>  }

+1

VD>  #endregion object  Members
  
VD>}

VD>module Program
VD>{
VD>  Main() : void // используются алиасы типов, а не полные имена вроде System.Void
VD>  {
VD>    def calc(text : string) // имена локальных функций и переменных в кэмелКэйсе
VD>    {
VD>      def lexer(text : string) : list[Token] // типы у локальных функций указываю только когда это помогает понят суть функции
VD>      {
VD>        mutable index = 0;
        
VD>        def peek()
VD>        {
VD>          if (index >= text.Length) '\0' else text[index];

Почему не на отдельных строках ?

Мне кажется однострочное if выражение лучше использовать только при инициализации.
def x = if(y > 1) f() else g();

VD>        } // пустых строк между описаниями локальных функций нет

И далее идут пустые строки между локальными функциями.
На мой взгляд не стоит делать это обязательным.

VD>        def read()
VD>        {
VD>          def ch = peek(); // переменные желательно отбивать от остального кода одной строкой (не строгое правило)

Как раз всегда получается что создается одна пустая строка, чтобы повысить читаемость.
Думаю стоит это сделать строгим правилом.

VD>          when (index < text.Length)
VD>            index++; // выражение внутри макры "when" всегда на новой строке и всегда заканчивается ";"
+1
VD>          ch
VD>        }
VD>        def isDigit(ch) { ch >= '0' && ch <= '9' } // мелкие функции можно описывать инлайном
VD>        def number(ch : char, accumulator : int = 0) : int
VD>        { // опять же табличное форматирование, где одно улучшает читаемость.

+1
Кстати, а в интеграции есть опция для создания табличного форматирования ?

VD>          def highOrderValue    = accumulator * 10; // если переменные повышают читабельность, то разносим 
VD>          def currentOrderValue = ch - '0' : int;   // выражение на несколько строк и для его частей вводим перепменные
VD>          def currentValue      = highOrderValue + currentOrderValue;
          
VD>          if (isDigit(peek())) // если ветка if-а - это одно выражение, то не в коем случае не используем { и } !

+1
Только за. Мне не нравятся лишние фигурные скобки когда они не нужны.

VD>            number(read(), currentValue) // если значение выражения является возвращаемым значением функции, то ";" не ставим!

Я так понимаю это для того чтобы было понятно что есть возвращаемое значение ?

VD>          else
VD>            currentValue
VD>        }
        
VD>        def loop(res : list[Token]) : list[Token]
VD>        { // все открывающие скобки, кроем тел лябд и именованных блоков, начинаются с новой стоки
VD>          def ch = read();

VD>          match (ch)
VD>          {
VD>            | '('                   => loop(Token.OpenBrace(index)  :: res)
VD>            | ')'                   => loop(Token.CloseBrace(index) :: res)
VD>            | ' ' | '\t'            => loop(res) // игнорируем пробелы
VD>            | '+' | '-' | '*' | '/' => loop(Token.Operator(index, ch.ToString()) :: res)
VD>            | '\0'                  => res.Reverse()
VD>            | _ when isDigit(ch)    => loop(Token.Number(index, number(ch)) :: res)
VD>            | _ => // если вхождение match-а не влазит в одну строку, то...
VD>              // переносим все выражения на следующую строку и начинаем их с отбивкой в одну табуляцию от "|" (начала паттерна)
VD>              WriteLine(string(' ', index - 1) + "^");
VD>              WriteLine($"ожидается число или оператр (в позиции $index)");
VD>              (Token.Error(index) :: res).Reverse() // опять же возвращаемое значение не заканчивается ";"
VD>          }

Тот же вопрос насчет автоматического табличного форматирования ?

VD>        }
        
VD>        loop([])
VD>      }
     
  ... <skip/>


Постараюсь добавить в документ стиля RSDN поправки и будет документ для Nemerle
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.