И еще раз о goto
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.04.13 14:49
Оценка: 8 (3) -2
Нашелся прикльный примерчик где использование goto выглядит как минимум не хуже альтернативного варианта.

Вопросов два:
1. Какой вариант вам нравится больше?
2. Можно предложить какой-то другой варинат который был бы лучше чем два предложенных?

Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).

Вариант с goto:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  if (_bestResult == null)                 goto good;
  if (endPos     > _bestResult.EndPos)     goto good;
  if (endPos     < _bestResult.EndPos)     return;
  if (startPos   < _bestResult.StartPos)   goto good;
  if (startPos   > _bestResult.StartPos)   return;
  if (stackLevel < _bestResult.StackLevel) goto good;
  if (stackLevel > _bestResult.StackLevel) return;
  if (startState < _bestResult.StartState) goto good;
  return;
good:
  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);

}

Вариант без goto:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  if (this._bestResult != null)
  {
    if (endPos <= this._bestResult.EndPos)
    {
      if (endPos < this._bestResult.EndPos)
        return;
      if (startPos >= this._bestResult.StartPos)
      {
        if (startPos > this._bestResult.StartPos)
          return;
        if (stackLevel >= this._bestResult.StackLevel)
        {
          if (stackLevel > this._bestResult.StackLevel)
            return;
          if (startState >= this._bestResult.StartState)
            return;
        }
      }
    }
  }

  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: И еще раз о goto
От: IT Россия linq2db.com
Дата: 04.04.13 15:00
Оценка: 7 (2) +1 -2 :))) :))) :))
Здравствуйте, VladD2, Вы писали:

void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  for (;;)
  {
    if (_bestResult == null)                 break;
    if (endPos     > _bestResult.EndPos)     break;
    if (endPos     < _bestResult.EndPos)     return;
    if (startPos   < _bestResult.StartPos)   break;
    if (startPos   > _bestResult.StartPos)   return;
    if (stackLevel < _bestResult.StackLevel) break;
    if (stackLevel > _bestResult.StackLevel) return;
    if (startState < _bestResult.StartState) break;
    return;
  }

  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
}
Если нам не помогут, то мы тоже никого не пощадим.
Re: И еще раз о goto
От: Razard Россия  
Дата: 04.04.13 15:05
Оценка: 22 (2) +7
Здравствуйте, VladD2, Вы писали:

VD>Нашелся прикльный примерчик где использование goto выглядит как минимум не хуже альтернативного варианта.


Приверженность догмам = отсутствие собственного развития.
goto один из основных операторов вычислительных систем. Выбрасывать его из использования полностью также глупо, как отказываться от морковки потому что цвет не нравится.
Все хорошо в меру.
Re: И еще раз о goto
От: Evgeny.Panasyuk Россия  
Дата: 04.04.13 15:06
Оценка: +1 :)
http://www.youtube.com/watch?v=c76xD3qNLc4&amp;t=49m26s

Я очень горд, что в этой книжке (Elements of Programming) есть, вы сейчас просто @#$%&%@#, GOTOS. Почему? Потому что в какой-то момент мы показываем, специально, потому что знаем, что вы будете кричать БУУУУУ и писать письма, может быть не все, но некоторые — мне всегда пишут письма что я дурак — потому что я не верю в объектную ориентацию, я использую goto — пропащий человек. И многие люди, в программировании есть такая идея что люди считают что это очень мило написать незнакомому человеку письмо говорящие что "ты дурак". Даже если вы так думаете — вы мне не говорите, потому что — не нужно, не обязательно.
Мы используем goto, для чего — потому что у нас есть структура которая реально является конечным автоматом. Если вы описываете конечный автомат, что он делает — он переходит из состояния этого в состояние то. Как нужно переходить из одного состояния в другое? Есть правильная инструкция — называется goto: идите от туда — туда. И структура программы становится очень элегантной.
То есть идея Дейкстры, Дейкстра великий человек — вы не думайте что $#%@#$%@#$, но он конечно же был не прав, потому что он думал, что плохая программа, потому что она пользуется какой-то синтаксической структурой. Нет — программа плохая, если она плохая.
То есть может быть очень красивая программа на языке Assembler — очень элегантная. Может быть очень плохая программа на Java, уверяю вас.
Немецкий язык такой непоэтичный — но какая поэзия Самые красивые песни на каком языке? На немецком — Шуберт — необыкновенная красота. Хотя у них там гортанный, странный язык, но невероятно красивый.
Всё можно сделать. goto может быть красивым. Я не верю в синтаксические лишения в семантических вопросах.
В меня всю жизнь камнями кидают, потому что я всё время такие вещи говорю — и мне говорят что я дурак. Но я не пытаюсь просто сказать дерзость. Я на самом деле пытаюсь объяснить какие-то вещи и в этой книжке никаких дерзостей.

Re: И еще раз о goto
От: fin_81  
Дата: 04.04.13 15:21
Оценка:
Здравствуйте, VladD2, Вы писали:

Думать не охота, вроде можно написать с использованием || (ленивое или).
Re[2]: И еще раз о goto
От: WolfHound  
Дата: 04.04.13 15:27
Оценка:
Здравствуйте, fin_81, Вы писали:

_>Думать не охота, вроде можно написать с использованием || (ленивое или).

Можно. Но там жуткая лапша получится...
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: И еще раз о goto
От: WolfHound  
Дата: 04.04.13 15:27
Оценка: +3 :)
Здравствуйте, IT, Вы писали:

И чем это лучше варианта с goto?
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: И еще раз о goto
От: vmpire Россия  
Дата: 04.04.13 15:41
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Нашелся прикльный примерчик где использование goto выглядит как минимум не хуже альтернативного варианта.


VD>Вопросов два:

VD>1. Какой вариант вам нравится больше?
VD>2. Можно предложить какой-то другой варинат который был бы лучше чем два предложенных?

Например, так:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
    _bestResultsCount++;

    bool isGood = false;
    if (_bestResult == null)                      isGood = true;
    else if (endPos     > _bestResult.EndPos)     isGood = true;
    else if (endPos     < _bestResult.EndPos)     return; // или isGood = false;, может пригодится при усложнении логики в конце метода
    else if (startPos   < _bestResult.StartPos)   isGood = true;
    else if (startPos   > _bestResult.StartPos)   return;
    else if (stackLevel < _bestResult.StackLevel) isGood = true;
    else if (stackLevel > _bestResult.StackLevel) return;
    else if (startState < _bestResult.StartState) isGood = true;
    if (isGood)
    {
        _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
    }
}


Но вообще — я тоже за то чтобы не избегать goto любой ценой. И при этом нужно всегда помнить, что break, continue и return не из конца метода — это всё то же самое goto только в специализированном виде. И они точно так же могут запутать логику, как goto, применённый для тех же целей.

В процессе развития языков программирования были выделены эти три типовых варианта использования goto, покрывающих 99% потребностей в нём.
Для этих трёх случаев и были сделаны специализированные конструкции, чтобы несколько улучшить читаемость кода и ограничить неправильное их использование.
Но нужно помнить, что оставшийся 1% всё-таки встречается, и в этом случае избавление от goto может привести к усложнению кода.
Хотя, мне кажется, что пример TS — не тот случай
Re: И еще раз о goto
От: fddima  
Дата: 04.04.13 15:46
Оценка:
Здравствуйте, VladD2, Вы писали:

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

PS: Не должен ли _bestResultsCount инкрементироваться перед присвоением _bestResults? А то это больше похоже на _resultsCount. (Хотя понятно что судить сложно).
Re[3]: И еще раз о goto
От: IT Россия linq2db.com
Дата: 04.04.13 15:49
Оценка: -1 :))) :))) :)))
Здравствуйте, WolfHound, Вы писали:

WH>И чем это лучше варианта с goto?


Тем что никто не поступается принципами и совесть остаётся чистой как утренняя роса
Если нам не помогут, то мы тоже никого не пощадим.
Re: И еще раз о goto
От: avpavlov  
Дата: 04.04.13 15:51
Оценка:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  if (_bestResult != null) {
   if      (endPos < _bestResult.EndPos) 
     return; 
   else if (endPos == bestResult.EndPos && startPos > _bestResult.StartPos)   
     return;
   else if (endPos == bestResult.EndPos && startPos == _bestResult.StartPos && stackLevel > _bestResult.StackLevel) 
     return;
 }
  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
Re[2]: И еще раз о goto
От: avpavlov  
Дата: 04.04.13 15:53
Оценка:
Здравствуйте, avpavlov, Вы писали:

A>
A>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
A>{
A>  _bestResultsCount++;

A>  if (_bestResult != null) {
A>   if      (endPos < _bestResult.EndPos) 
A>     return; 
A>   else if (endPos == bestResult.EndPos && startPos > _bestResult.StartPos)   
A>     return;
A>   else if (endPos == bestResult.EndPos && startPos == _bestResult.StartPos && stackLevel > _bestResult.StackLevel) 
A>     return;
A> }
A>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);

A>


Обрати внимание, в моем варианте четко видно, при каких условиях аналиpируем startPosи при каких — stackLevel. В обоих исходных вариантах этого видно не было
Re: И еще раз о goto
От: fin_81  
Дата: 04.04.13 16:24
Оценка:
Здравствуйте, VladD2, Вы писали:

А код сам правильный? Новый отрезок должен включать предыдущий лучший отрезок?
Re: И еще раз о goto
От: Abyx Россия  
Дата: 04.04.13 17:12
Оценка: 32 (9) +18
Здравствуйте, VladD2, Вы писали:

VD>
VD>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
VD>{
VD>  _bestResultsCount++;

VD>  if (_bestResult == null)                 goto good;
VD>  if (endPos     > _bestResult.EndPos)     goto good;
VD>  if (endPos     < _bestResult.EndPos)     return;
VD>  if (startPos   < _bestResult.StartPos)   goto good;
VD>  if (startPos   > _bestResult.StartPos)   return;
VD>  if (stackLevel < _bestResult.StackLevel) goto good;
VD>  if (stackLevel > _bestResult.StackLevel) return;
VD>  if (startState < _bestResult.StartState) goto good;
VD>  return;
VD>good:
VD>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
VD>

VD>}

эта функция делает три вещи — инкремент, хитрый if, new
хитрый if слишком хитрый, и потому он нарушает SRP
по этому код должен выглядеть так

bool isBetter(int startPos, int endPos, int startState, int stackLevel) const 
{
  if (endPos     > _bestResult.EndPos)     return true;
  if (endPos     < _bestResult.EndPos)     return false;
  if (startPos   < _bestResult.StartPos)   return true;
  if (startPos   > _bestResult.StartPos)   return false;
  if (stackLevel < _bestResult.StackLevel) return true;
  if (stackLevel > _bestResult.StackLevel) return false;
  if (startState < _bestResult.StartState) return true;
  return false;
}

void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  if (_bestResult == null || isBetter(startPos, endPos, startState, stackLevel))
      _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
In Zen We Trust
Re: И еще раз о goto
От: Abyx Россия  
Дата: 04.04.13 17:15
Оценка: +2 -3 :)
Здравствуйте, VladD2, Вы писали:

VD>Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).


если производительность имеет значение, не пишите на C#, или найдите компилятор который умеет инлайнить функции
In Zen We Trust
Re[2]: И еще раз о goto
От: andy1618 Россия  
Дата: 04.04.13 18:47
Оценка: +1
Здравствуйте, avpavlov, Вы писали:

A>
A>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
A>{
A>  _bestResultsCount++;

A>  if (_bestResult != null) {
A>   if      (endPos < _bestResult.EndPos) 
A>     return; 
A>   else if (endPos == bestResult.EndPos && startPos > _bestResult.StartPos)   
A>     return;
A>   else if (endPos == bestResult.EndPos && startPos == _bestResult.StartPos && stackLevel > _bestResult.StackLevel) 
A>     return;
A> }
A>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);

A>


А где анализ startState?
Re[3]: И еще раз о goto
От: avpavlov  
Дата: 04.04.13 18:52
Оценка:
A>А где анализ startState?

ага, пропустил
Re: И еще раз о goto
От: andy1618 Россия  
Дата: 04.04.13 19:20
Оценка: 3 (1)
Здравствуйте, VladD2, Вы писали:

VD>2. Можно предложить какой-то другой варинат


Вариант без return:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;

  bool isGood;
  for (;;) {
    if (_bestResult == null)                   { isGood = true; break; };
    if (endPos != _bestResult.EndPos)          { isGood = endPos > _bestResult.EndPos; break; };
    if (startPos   != _bestResult.StartPos))   { isGood = startPos < _bestResult.StartPos; break; };
    if (stackLevel != _bestResult.StackLevel)) { isGood = stackLevel < _bestResult.StackLevel; break; };
    isGood = startState < _bestResult.StartState;
    break;
  }

  if (isGood)
    _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
}
Re[2]: И еще раз о goto
От: artelk  
Дата: 04.04.13 19:30
Оценка: 67 (4)
Здравствуйте, Abyx, Вы писали:

A>или найдите компилятор который умеет инлайнить функции


MethodImplOptions.AggressiveInlining
Re[3]: И еще раз о goto
От: fddima  
Дата: 04.04.13 20:55
Оценка:
Здравствуйте, artelk, Вы писали:

A>>или найдите компилятор который умеет инлайнить функции

A>MethodImplOptions.AggressiveInlining
Спасибо, больше и человеческое!
Re[2]: И еще раз о goto
От: fddima  
Дата: 04.04.13 20:57
Оценка:
Здравствуйте, Abyx, Вы писали:

A>если производительность имеет значение, не пишите на C#, или найдите компилятор который умеет инлайнить функции

В этом форуме не пишут на C#. Если нечего сказать — прохожите дальше. И функция делающая 3 вещи — делает их максимально быстро в том языке в котором реализована. На ассемблере бы, проверок было бы почти в два раза меньше, т.к. после результата сравения мы совершенно спокойно могли бы сделать:
cmp eax, some
jg good
jl bad
cmp eax, some2
jg good
jl bad

В общем — следующий.
Re[2]: И еще раз о goto
От: SV.  
Дата: 04.04.13 20:58
Оценка:
Здравствуйте, IT, Вы писали:

IT>
IT>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
IT>{
IT>  _bestResultsCount++;

IT>  for (;;)
IT>  {
IT>    if (_bestResult == null)                 break;
IT>    if (endPos     > _bestResult.EndPos)     break;
IT>    if (endPos     < _bestResult.EndPos)     return;
IT>    if (startPos   < _bestResult.StartPos)   break;
IT>    if (startPos   > _bestResult.StartPos)   return;
IT>    if (stackLevel < _bestResult.StackLevel) break;
IT>    if (stackLevel > _bestResult.StackLevel) return;
IT>    if (startState < _bestResult.StartState) break;
IT>    return;
IT>  }

IT>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
IT>}
IT>


Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок? Тогда не пришлось бы таскать за собой уродство for (;), а спорам на тему goto пришел бы жирный конец.
Re[2]: И еще раз о goto
От: fddima  
Дата: 04.04.13 21:02
Оценка:
Здравствуйте, andy1618, Вы писали:

Вариант не так уж плох. Единственное, что в исходном, посте было указано — "Производительность имеет значение". Введение дополнительных переменных, при там же самом количестве бранчинга, да ещё в дотнете — ничем хорошим не скажется, хотя это и будет сложно заметить в микроскоп — но это не значит, что это не важно.
Re[3]: И еще раз о goto
От: fddima  
Дата: 04.04.13 21:04
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок? Тогда не пришлось бы таскать за собой уродство for (;), а спорам на тему goto пришел бы жирный конец.

На правах дурной идеи — присвоить блоками имена? Но тогда лучше goto. На самом деле, тут уже мысль кто-то говорил — глупо отрицать существование goto, пока в процессоре существует jmp.
Re[4]: И еще раз о goto
От: SV.  
Дата: 04.04.13 21:17
Оценка:
Здравствуйте, fddima, Вы писали:

SV.>>Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок? Тогда не пришлось бы таскать за собой уродство for (;), а спорам на тему goto пришел бы жирный конец.

F> На правах дурной идеи — присвоить блоками имена?

Да, но как?

>Но тогда лучше goto. На самом деле, тут уже мысль кто-то говорил — глупо отрицать существование goto, пока в процессоре существует jmp.


В процессоре много чего есть. Не все из этого находит отражение в си-подобных языках. break дополнительно ограничен по сравнению с goto (переход за пределы некоторого блока, а не куда черт пошлет) и это ограничение на ровном месте делает код читабельнее. Речь об этом ограничении, а не о том, как назвать такую конструкцию. Привести ее к goto-виду можно будет автоматически. Не откомпилировать в jmp, а именно заменить на goto.

Вот если вы придумаете пример, который показывал бы необходимость переходить, куда черт пошлет...
Re[3]: И еще раз о goto
От: Abyx Россия  
Дата: 04.04.13 21:37
Оценка:
Здравствуйте, fddima, Вы писали:

A>>если производительность имеет значение, не пишите на C#, или найдите компилятор который умеет инлайнить функции

F> В этом форуме не пишут на C#.
тоже не читатель, да? у ОПа код на c#

F>Если нечего сказать — прохожите дальше. И функция делающая 3 вещи — делает их максимально быстро в том языке в котором реализована. На ассемблере бы, проверок было бы почти в два раза меньше, т.к. после результата сравения мы совершенно спокойно могли бы сделать:

F>
F>cmp eax, some
F>jg good
F>jl bad
F>cmp eax, some2
F>jg good
F>jl bad
F>

FYI, ветвления нынче не в моде, так сейчас никто не пишет
In Zen We Trust
Re[5]: И еще раз о goto
От: fddima  
Дата: 04.04.13 21:38
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Да, но как?

Написал бы кады б знал.

SV.>Вот если вы придумаете пример, который показывал бы необходимость переходить, куда черт пошлет...

Дело не в том, я там написал ниже.
Тут есть предикат и реакция на него в 3-х состояниях: меньше, больше, равно. Те 2 проверки (больше-меньше), что приведены в исходном коде — на самом деле одна проверка, и нужен условный переход по разным условиям исходя из одного предиката, а не повторя тот же самый предикат в их инверсиях. Проблема не в локах, а в логике, которую, даёт ассемблер, но не дают C-подобные языки. Наверное так.
Re[4]: И еще раз о goto
От: fddima  
Дата: 04.04.13 21:56
Оценка:
Здравствуйте, Abyx, Вы писали:

A>FYI, ветвления нынче не в моде, так сейчас никто не пишет

В моде ли дёргать память (даже L1) кеш, тогда, когда это не нужно?
Re[3]: И еще раз о goto
От: fddima  
Дата: 04.04.13 23:08
Оценка:
Здравствуйте, fddima, Вы писали:

A>>если производительность имеет значение, не пишите на C#, или найдите компилятор который умеет инлайнить функции

F> В этом форуме не пишут на C#.
Не иначе как у меня произошло Немерле головного мозга. =) Должно было видимо быть так — в этом форуме пишут на всём чем угодно, кроме того, на чём работают реальный софт.
Если серьёзно — то реально, форум, думал другой. =)
Re[2]: И еще раз о goto
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 05.04.13 02:07
Оценка: 6 (1)
Здравствуйте, andy1618, Вы писали:

VD>>2. Можно предложить какой-то другой варинат


A>Вариант без return:

A>...

И с одним if'ом:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
    _bestResultsCount++;
    if (_bestResult == null || 
        (endPos     > _bestResult.EndPos) || 
       !(endPos     < _bestResult.EndPos) || 
        (startPos   < _bestResult.StartPos) || 
       !(startPos   > _bestResult.StartPos) || 
        (stackLevel < _bestResult.StackLevel) || 
       !(stackLevel > _bestResult.StackLevel) || 
        (startState < _bestResult.StartState))
        {
         _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
        }
}
Маньяк Робокряк колесит по городу
Re[3]: И еще раз о goto
От: IT Россия linq2db.com
Дата: 05.04.13 03:07
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок? Тогда не пришлось бы таскать за собой уродство for (;), а спорам на тему goto пришел бы жирный конец.


Всё уже давно придумано — http://nemerle.org/wiki/index.php?title=Core_expressions_(ref)#Named_block
Если нам не помогут, то мы тоже никого не пощадим.
Re: И еще раз о goto
От: C.A.B LinkedIn
Дата: 05.04.13 06:39
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Вариант с goto:
VD>
VD>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
VD>{
VD>  _bestResultsCount++;

VD>  if (_bestResult == null)                 goto good;
VD>  if (endPos     > _bestResult.EndPos)     goto good;
VD>  if (endPos     < _bestResult.EndPos)     return;
VD>  if (startPos   < _bestResult.StartPos)   goto good;
VD>  if (startPos   > _bestResult.StartPos)   return;
VD>  if (stackLevel < _bestResult.StackLevel) goto good;
VD>  if (stackLevel > _bestResult.StackLevel) return;
VD>  if (startState < _bestResult.StartState) goto good;
VD>  return;
VD>good:
VD>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
VD>

VD>}

Из праздного любопытства(не знаю C#), почему нельзя так написать:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail){ 
  _bestResultsCount++;
  if (_bestResult == null 
  || endPos     > _bestResult.EndPos 
  || startPos   < _bestResult.StartPos 
  || stackLevel < _bestResult.StackLevel 
  || startState < _bestResult.StartState){
    _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail)}
  return;   
  }
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[2]: И еще раз о goto
От: andy1618 Россия  
Дата: 05.04.13 06:57
Оценка: 6 (1)
Здравствуйте, C.A.B, Вы писали:

CAB>Из праздного любопытства(не знаю C#), почему нельзя так написать:

CAB>
CAB>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail){ 
CAB>  _bestResultsCount++;
CAB>  if (_bestResult == null 
CAB>  || endPos     > _bestResult.EndPos 
CAB>  || startPos   < _bestResult.StartPos 
CAB>  || stackLevel < _bestResult.StackLevel 
CAB>  || startState < _bestResult.StartState){
CAB>    _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail)}
CAB>  return;   
CAB>  }
CAB>


Написать можно, но работать будет неверно
Контрпример — кейс: _bestResult != null, endPos < _bestResult.EndPos, все остальные условия верны.
В исходном примере будет return, в вашем — нет.
Re[3]: И еще раз о goto
От: andy1618 Россия  
Дата: 05.04.13 07:10
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок?

SV.>...

Кстати, когда лет 15 назад в первый раз довелось писать макрос для Excel — порадовало, что в Visual Basic конструкции End, Exit можно конкретизировать: End If, End For, Exit For и т.п.
Re[3]: И еще раз о goto
От: C.A.B LinkedIn
Дата: 05.04.13 08:55
Оценка: 1 (1)
Здравствуйте, andy1618, Вы писали:
CAB>>Из праздного любопытства(не знаю C#), почему нельзя так написать:
A>Написать можно, но работать будет неверно
И то правда.
Немного помедетировав я получил такой вариант:
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail){ 
  _bestResultsCount++;
  if (_bestResult == null 
  || (endPos     > _bestResultEndPos)
  || (startPos   < _bestResultStartPos   && endPos >= _bestResultEndPos)
  || (stackLevel < _bestResultStackLevel && endPos >= _bestResultEndPos && startPos <= _bestResultStartPos) 
  || (startState < _bestResultStartState && endPos >= _bestResultEndPos && startPos <= _bestResultStartPos && stackLevel <= _bestResultStackLevel)){
    _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail)}
  return;   
  }

Определённо сливающий goto и по скорости и по читабельности.
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re: И еще раз о goto
От: fin_81  
Дата: 05.04.13 09:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>
  Скрытый текст
  if (_bestResult == null)                 goto good;
  if (endPos     > _bestResult.EndPos)     goto good;
  if (endPos     < _bestResult.EndPos)     return;
  if (startPos   < _bestResult.StartPos)   goto good;
  if (startPos   > _bestResult.StartPos)   return;
  if (stackLevel < _bestResult.StackLevel) goto good;
  if (stackLevel > _bestResult.StackLevel) return;
  if (startState < _bestResult.StartState) goto good;
  return;
good:


Думать не охота. Сами проверяйте корректность и быстродействие.

if (_bestResult != null) {
  if (endPos     < _bestResult.EndPos)     return;
  if (startPos   > _bestResult.StartPos)   return;
  if (stackLevel > _bestResult.StackLevel) return;
  if (startState >= _bestResult.StartState) return;
}
Re: И еще раз о goto
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.04.13 09:45
Оценка: 4 (1)
Здравствуйте, VladD2, Вы писали:
VD>1. Какой вариант вам нравится больше?
Несогласен с обоими.
VD>2. Можно предложить какой-то другой варинат который был бы лучше чем два предложенных?
Я бы предложил такой вариант, который понятен.
По факту происходит сравнение по композитному ключу, но понять это можно только путём крепкой медитации.
Так что лучше всего понятен был бы вариант типа такого:
static IComparer<RecoveryResult> _bestComparer = new CompositeKeyComparer(rr=>new {-rr.EndPos, rr.StartPos, rr.StackLevel, rr.StartState});
void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultCoun++
  _bestResult = Min(
    _bestResult, 
    new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail), 
    _bestComparer);
}


VD>Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).

А это уже другой вопрос. После того, как написан понятный код, в котором сложно сделать ошибку, можно заняться оптимизацией.
С тем, чтобы получить ассемблерный выхлоп как можно ближе к тому, который ты привёл. Пусть этим преобразованием занимается платформа или фреймворк.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: И еще раз о goto
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.04.13 10:31
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).


Если нельзя выделить и потом заинлайнить функцию сравнения так, чтобы это не портило производительность... или выбрасывайте компилятор, или грош цена всем рассказам про ценность компилируемых языков
The God is real, unless declared integer.
Re[3]: И еще раз о goto
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 05.04.13 10:37
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Интересно, можно ли придумать красивый синтаксис, чтобы break привязывался к любому блоку и было сразу понятно, чтО он брейкает — цикл, свич или текущий блок?


Меткам конструкций уже лет 20 как минимум, в Perl они были с очень ранних версий. Реализовать в C-подобном языке — раз плюнуть, в другом — тем более.

Вот почему другие не хотят заимствовать, а вместо этого кричат о принципах — вопрос конечно интересный (c)
The God is real, unless declared integer.
Re[2]: И еще раз о goto
От: MTD https://github.com/mtrempoltsev
Дата: 05.04.13 11:24
Оценка: +1 :)
С таким кодом смело на сюда
Re: И еще раз о goto
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.04.13 11:37
Оценка:
Здравствуйте, VladD2, Вы писали:


VD> if (_bestResult == null) goto good;

VD> if (endPos > _bestResult.EndPos) goto good;
VD> if (endPos < _bestResult.EndPos) return;
VD> if (startPos < _bestResult.StartPos) goto good;
VD> if (startPos > _bestResult.StartPos) return;
VD> if (stackLevel < _bestResult.StackLevel) goto good;
VD> if (stackLevel > _bestResult.StackLevel) return;
VD> if (startState < _bestResult.StartState) goto good;
VD> return;

По сути это у тебя Компарер. Я бы сделал функцию и анализировал её значение.
и солнце б утром не вставало, когда бы не было меня
Re[2]: И еще раз о goto
От: IT Россия linq2db.com
Дата: 05.04.13 13:26
Оценка:
Здравствуйте, Sinclair, Вы писали:

VD>>Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).

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

А если ни платформа, ни фреймворк этого делать не умеют, а нужно прямо сейчас?
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: И еще раз о goto
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.04.13 13:45
Оценка:
Здравствуйте, IT, Вы писали:


IT>А если ни платформа, ни фреймворк этого делать не умеют, а нужно прямо сейчас?

Значит нужно Писать DSL с переводом в инлайн на OPT кодах
и солнце б утром не вставало, когда бы не было меня
Re[2]: И еще раз о goto
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.04.13 14:29
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я бы предложил такой вариант, который понятен.


Для начала твой вариант не верен. Вот исходный вариант, который переписывался:
def filterMax(res, func : RecoveryResult -> int) : array[RecoveryResult]
{
  if (res.Length == 0)
    res
  else
  {
    def max = res.Max(func);
    def bestResults = res.Filter(x => func(x) == max);
    bestResults.ToArray()
  }
}
def filterMin(res, func : RecoveryResult -> int) : array[RecoveryResult]
{
  if (res.Length == 0)
    res
  else
  {
    def min = res.Min(func);
    def bestResults = res.Filter(x => func(x) == min);
    bestResults.ToArray()
  }
}

def bestResults1 = filterMax(res.ToArray(), x => x.EndPos);
def bestResults2 = filterMin(bestResults1,  x => x.StartPos);
def bestResults3 = filterMin(bestResults2,  x => x.StackLevel);
def bestResults4 = filterMin(bestResults3,  x => x.StartState);
assert(bestResults4.Length == 1);


S>По факту происходит сравнение по композитному ключу, но понять это можно только путём крепкой медитации.


Я уже писал, что производительность важна. По этому варианты с замыканиями, созданием объектов и списками не катят принципиально.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: И еще раз о goto
От: fin_81  
Дата: 05.04.13 15:11
Оценка:
Здравствуйте, VladD2, Вы писали:

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


S>>Я бы предложил такой вариант, который понятен.


VD>Для начала твой вариант не верен. Вот исходный вариант, который переписывался:

VD>

Так что там на счет правильности (эквивалентности) кода c goto?
Re[3]: И еще раз о goto
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.04.13 16:27
Оценка:
Здравствуйте, IT, Вы писали:
IT>А если ни платформа, ни фреймворк этого делать не умеют, а нужно прямо сейчас?
Я бы всё равно начал с такого кода. А потом уже профайлером смотрел, насколько там всё плохо.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: И еще раз о goto
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.04.13 16:33
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Для начала твой вариант не верен. Вот исходный вариант, который переписывался:

прости, я немерле не умею. В чём ошибка-то?
Кстати, немерлёвый вариант тоже копец как непонятен.
VD>Я уже писал, что производительность важна. По этому варианты с замыканиями, созданием объектов и списками не катят принципиально.
Ну, тут идея-то в том, чтобы спрятать goto под капот, где ему и место. Т.е. описывать сравнение я предлагаю в терминах составного ключа, а генерировать код — как раз такой, как ты написал (с goto).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: И еще раз о goto
От: Философ Ад http://vk.com/id10256428
Дата: 05.04.13 17:12
Оценка: 2 (1) +1
Здравствуйте, fddima, Вы писали:

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


A>>>или найдите компилятор который умеет инлайнить функции

A>>MethodImplOptions.AggressiveInlining
F> Спасибо, больше и человеческое!


здесь

надо только не забыть, что 4.5 ставится только на висту, а XP ещё больше трети машин
Всё сказанное выше — личное мнение, если не указано обратное.
Re[3]: И еще раз о goto
От: fin_81  
Дата: 05.04.13 17:16
Оценка:
Здравствуйте, VladD2, Вы писали:

S>>Я бы предложил такой вариант, который понятен.


VD>Для начала твой вариант не верен. Вот исходный вариант, который переписывался:


Как я понимаю этот каскад фильтров ищет покрывающие-всех отрезки из множества. При этом, если окажется несколько, они должны быть одинаковы.

Вариант с goto, возможно, короче и понятнее. Но он не быстрый, так как излишне часто создает (new) эти промежуточные отрезки. Создание объекта на порядки тяжелее чем целочисленное сравнение. Почему создается отрезок (RecoveryResult), если проще и быстрее сохранить текущие целочисленные минимумы и максимумы отдельно?

В общем очень много вопросов к самой реализации алгоритма, который надо еще угадать по обфусцированному коду, оптимизацией назвать это чудо трудновато.

Сперва стоит написать что должен делать алгоритм, а после можно повоевать над реализациями этого алгоритма.

ps. Вспомнил тему из форума бд с зиг, в котором он(а) пытался(ась) напрячь остальных посетителей угадать структуру бд и оптимизировать этот запрос.
Re[5]: И еще раз о goto
От: fddima  
Дата: 05.04.13 18:18
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>надо только не забыть, что 4.5 ставится только на висту, а XP ещё больше трети машин

Это я в курсе. Просто на C# — с ручным! инлайнингом довелось наиграться, а этот ключик 4.5 фреймворка — пропустил.
Re[4]: И еще раз о goto
От: IT Россия linq2db.com
Дата: 05.04.13 19:00
Оценка: +2
Здравствуйте, Sinclair, Вы писали:

IT>>А если ни платформа, ни фреймворк этого делать не умеют, а нужно прямо сейчас?

S>Я бы всё равно начал с такого кода. А потом уже профайлером смотрел, насколько там всё плохо.

Честно говоря, мне вообще не очень понятен масштаб трагедии, поэтому не могу сказать как бы сам поступил
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: И еще раз о goto
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.04.13 02:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>прости, я немерле не умею. В чём ошибка-то?


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

S>Кстати, немерлёвый вариант тоже копец как непонятен.


А ты вчитайся. Лично я его написал за пару сикунд. Оно очевиден. А вот с реализацией на ифах я накосячил (тут этот косяк несколько раз повторили).

S>Ну, тут идея-то в том, чтобы спрятать goto под капот, где ему и место. Т.е. описывать сравнение я предлагаю в терминах составного ключа, а генерировать код — как раз такой, как ты написал (с goto).


Дык я же тебе говорю, что я за 5 минут написал вариант на списках и проверил его. Это и была оптимизация. И как это часто бывает, я в ней накосячил. Вольфхаунд поправил мою реализацию с использованием готу. Я переписал его код на ифах и понял, что получилось не сильно лучше (если не хуже). Вот и решил по обсуждать этот странный, на мой взгляд, феномен.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: И еще раз о goto
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.04.13 12:23
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А ты вчитайся. Лично я его написал за пару сикунд. Оно очевиден. А вот с реализацией на ифах я накосячил (тут этот косяк несколько раз повторили).

Угу. А чего там не использовано решение уравнения Больцано-Вейерштрасса заодно? Многословное изложение, основная цель которого — запутать читателя. Я верю, что ты написал его за пару секунд. А вот читать его нужно минимум несколько минут, чтобы понять суть происходящего.

VD>Дык я же тебе говорю, что я за 5 минут написал вариант на списках и проверил его. Это и была оптимизация. И как это часто бывает, я в ней накосячил. Вольфхаунд поправил мою реализацию с использованием готу. Я переписал его код на ифах и понял, что получилось не сильно лучше (если не хуже). Вот и решил по обсуждать этот странный, на мой взгляд, феномен.

Хуже. Потому что у нас нет "тройного" if-оператора, а блок схема алгортма сравнения по композитному ключу использует по три выхода из каждого блока.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: И еще раз о goto
От: mrTwister Россия  
Дата: 07.04.13 15:58
Оценка: +1
Здравствуйте, fddima, Вы писали:

F>хотя это и будет сложно заметить в микроскоп — но это не значит, что это не важно.


Вообще-то значит.
лэт ми спик фром май харт
Re[3]: И еще раз о goto
От: vdimas Россия  
Дата: 09.04.13 11:58
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

WH>И чем это лучше варианта с goto?


тем, что остальные безусловные операторы перехода, кроме goto, ограничены неким блоком кода.
Re[4]: И еще раз о goto
От: vdimas Россия  
Дата: 09.04.13 11:59
Оценка:
Здравствуйте, fddima, Вы писали:

F>На самом деле, тут уже мысль кто-то говорил — глупо отрицать существование goto, пока в процессоре существует jmp.


Ерунду этот кто-то говорил.
return, continue, break — это тоже операторы безусловного перехода.
Re: И еще раз о goto
От: B0FEE664  
Дата: 11.04.13 13:16
Оценка: :))
Здравствуйте, VladD2, Вы писали:

  Скрытый текст
VD>Нашелся прикльный примерчик где использование goto выглядит как минимум не хуже альтернативного варианта.

VD>Вопросов два:

VD>1. Какой вариант вам нравится больше?
VD>2. Можно предложить какой-то другой варинат который был бы лучше чем два предложенных?

VD>Производительность имеет значение, так что вариант на класса/лямбдах/дополнительных функциях/использующий лишние проверки не принимается (не приветствуется).


VD>Вариант с goto:

VD>
VD>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
VD>{
VD>  _bestResultsCount++;

VD>  if (_bestResult == null)                 goto good;
VD>  if (endPos     > _bestResult.EndPos)     goto good;
VD>  if (endPos     < _bestResult.EndPos)     return;
VD>  if (startPos   < _bestResult.StartPos)   goto good;
VD>  if (startPos   > _bestResult.StartPos)   return;
VD>  if (stackLevel < _bestResult.StackLevel) goto good;
VD>  if (stackLevel > _bestResult.StackLevel) return;
VD>  if (startState < _bestResult.StartState) goto good;
VD>  return;
VD>good:
VD>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
VD>

VD>}


VD>Вариант без goto:

VD>
VD>void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
VD>{
VD>  _bestResultsCount++;

VD>  if (this._bestResult != null)
VD>  {
VD>    if (endPos <= this._bestResult.EndPos)
VD>    {
VD>      if (endPos < this._bestResult.EndPos)
VD>        return;
VD>      if (startPos >= this._bestResult.StartPos)
VD>      {
VD>        if (startPos > this._bestResult.StartPos)
VD>          return;
VD>        if (stackLevel >= this._bestResult.StackLevel)
VD>        {
VD>          if (stackLevel > this._bestResult.StackLevel)
VD>            return;
VD>          if (startState >= this._bestResult.StartState)
VD>            return;
VD>        }
VD>      }
VD>    }
VD>  }

VD>  _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
VD>}
VD>


А зачем столько if'ов? Вот так надо:

void AddResult(int startPos, int endPos, int startState, int stackLevel, RecoveryStackFrame stackFrame, string text, int fail)
{
  _bestResultsCount++;
    
  if (
         null   == _bestResult
       ||
         endPos >  _bestResult.EndPos
       ||
       (
         endPos == _bestResult.EndPos && (
                                             startPos <  _bestResult.StartPos
                                           ||
                                           (
                                             startPos == _bestResult.StartPos && (
                                                                                   stackLevel  <  _bestResult.StackLevel
                                                                                   ||
                                                                                   (stackLevel == _bestResult.StackLevel && startState < _bestResult.StartState)
                                                                                 )
                                           )
                                         )
       )
     )                                  
  {
    _bestResult = new RecoveryResult(startPos, endPos, startState, stackLevel, stackFrame, text, fail);
  }
}
И каждый день — без права на ошибку...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.