Ненормальное программирование
Разработка веб-сайтов
JavaScript
Программирование
Комментарии 71
-22
Огромное Спасибо за чёткое и внятное изложение ценного материала!
Ваша публикация и рефакторинг кода: наш путь к быстрым, стабильным и нетребовательным к ресурсам приложениям.
Спасибо!
+1
Внешне очень похоже на копирайтинг. Поисковые движки копирайтинг любят, хабр — нет ^_^.
К прмеру, если бы вы написали «спасибо, узнал много нового» — никто бы не проголосовал или слабый плюс. А у вас хорошая такая фраза… По всем правилам, даже призыв к действию есть :).
0
Понятно. Слегка ошибся с аудиторией… :)
Однако, я многого еще не знаю! :)
Спасибо за статью и пояснения eyeofhell'у
+6
«Спасибо за статью и пояснения eyeofhell'у, купить ковры за смс недорого»

Извините, просто у вас очень прикольный стиль изложения)
+49
ммм. Я так понимаю, стрелять в ногу в одиночестве Вам надоело, и Вы решили набрать народ в клуб, заодно научив их отстреливать себе руки. Поддерживаю, зачотно!
+1
Прикольно применять вот так:

var x, y, z;

z = (x = 10, y = x + 20, x * y); 


Последняя запичсь запишется в результат z
0
Помню похожее — обмен переменных значениями без дополнительной переменной.

var a = 5, b = 10;

a = [b, b = a][0];
+2
Имхо это не так. Доп. Переменная тут есть в виде инлайн массива. Без доп переменных свап чисел делается математическими операциями))
+2
Переменная — это именованная область памяти, доступная для изменения по имени, а не любая
-1
Терминология это кончено классно, но факт останется фактом. Память выделена, и до конца окончания блока или запуска gc память не очистится.
+2
То, что делается мат. операциями — называется «обмен значений без дополнительной памяти». А в задаче «обмен значений без дополнительной переменной» использовать доп. память, если она не именованная — можно!
+1
Можно вот так a = b + (b=a, 0) или так a = (a = a ^ b, b = a ^ b, a ^ b) или сокращенно a ^= (b ^ (b=a))
+10
Вот таким образом можно получить массив от 0 до 9 во славу сатане:

(new Array(10+1))
    .join(' ')
    .split('')
    .map(function(el,i){ return i; })
+4
Если уж говорить о ES6, то там есть два варианта попроще:

[...new Array(10)].map((i, n) => n);

Array.from(new Array(10), (i, n) => n);
0
А что будет, если отрефакторить его с использованием map? Массив остался неизменным.
Да, есть такое. filter-map-reduce семейство функций на разрежённых массивах не работает с пропусками. Некоторые библиотеки в угоду производительности даже исключают разрежённые массивы из области своего применения.
+25
Кажется ребята ошиблись — надо было слово break заменить на goto и холивар был бы обеспечен )
+2
Тогда уж скорее gofrom: тут мы не переходим на метку, а наоборот, уходим от нее подальше.
+1
Кстати, у break на самом деле гораздо более скудные возможности по сравнению с goto. Например, нельзя «прыгнуть» внутрь цикла, да и вообще нельзя таким образом создать цикл. Это исключает появление такой неприятной для разработчиков компиляторов штуки, как irreducible flow graph.

Такая конструкция, может, и не очень целесообразна при ручном кодировании, но может быть очень полезна при кодогенерации. Особенно, учитывая, что сейчас есть множество языков, которые компилятся в JavaScript.
+3
По поводу добавления скобок, предполагаю что тут все просто — скобки это по сути оператор, который превращает то что внутри них в один expression. Если мы берем литерал «a» слева от оператора "=", то сам по себе литерал будет «lvalue expression». Заключаем его в скобки — снова получаем «lvalue expression». Насколько я помню, в скобки можно заключать иного всего без побочных эффектов.
0
Это отвечает на вопрос «как так случилось», но на вопрос «зачем так сделали» ответа, судя по всему, нет — скобки могут быть побочным эффектом того, как была написана грамматика.
+1
Скобки — универсальный механизм. Подозреваю, что данный конкретный случай вообще не представлен в грамматике и является следствием универсального механизма скобок. Не отключать же его для такого случая? :)
-1
Практически уверен, что так и есть. Однако это индикатор того, что грамматика могла бы быть составлена лучше — у lvalue обычно прописываются жесткие рамки.
0
Подозреваю, что это для большинства языков со скобочками так работает. На вскидку, c:

int main(int argc, char** argv) {
  int a = 0;
  (a) = 1;
  return 0;
}


Python:

a = 1
(a) = 2
0
Признаю, ошибся. Так действительно сделано во многих языках. Но менее странным оно от этого не выглядит :)
0
Скобки в грамматике в таких конструкциях как раз отвечают за order of operation. Лучше составить грамматику я думаю было бы более больно для синтаксиса. Т.к. под каждый случай прийдётся писать доп. правила для скобок.
0
Когда я составлял грамматику для своего языка, было просто три правила для присваивания. В упрощенном виде они выглядят так:

assign_identifier = identifier "=" expr
assign_member = expr "." identifier "=" expr
assign_index = expr "[" expr "]" "=" expr

Скобки могут быть быть слева от знака присваивания, но только в подвыражении, типа (a + b).pty = 1.
0
Я после университета конечно благополучно забыл как это правильно делается точно, но хорошо помню, что когда мы с одногруппником рожали свои грамматики, то долго мучались именно с order of operation и скобками. Конечно не могу сказать с уверенностью, но помоему скобки должны всё же учавствовать более одного раза.
0
Если интересно, в статье про написание парсера я предлагал довольно удобный способ описания order of operation в грамматике (правда, на сишарпе, но алгоритм применим к любому языку).
+5
Это переход не к метке, А к концу помеченного блока. Например, очень полезен в подобной логике:
checking: {
    while( x --> 0 ) {
        if( x % 10 === 0 ) break checking
    }
    throw Error( 'Чисел кратных 10 не найдено' )
}
+4
А ещё можно исполнять код после return-а. С помощью try-finally. Не только в JS, кстати.

function test(){
    // do something
    try {
        return true;
    }
    finally {
        console.log('Hey! :)');
        return false;
    }
}
+1
Вы не поверите, но в этом и есть суть finally — автоматически освобождать ресурсы после выхода из блока.
0
Знаете, мне довелось читать много стандартов языков программирования (С, С++, Fortran, EcmaScript, OpenMP, OpenACC, Posix). Из них ES 5.1 самый, имхо, простой для прочтения и (тут никакого сарказма) увлекательный. Поэтому я, не написавший ни одной продашн строчки на JS, с недоумением читал статью. Какого, простите, хрена нарушать нулевое правило программирования (RTFM)? Поэтому ваш сарказм здесь неуместен. И меня поражает сообщество, которое минусует в ответ на RTFM.

Из того, что мне запомнилось из работы над Jerry (https://github.com/Samsung/jerryscript) (Скажу честно — до сих пор жалею, что согласился на уговоры присоединиться к разработке и всей душой желаю смерти этому монстру):
1) BlockStatement очень похож на ObjectLiteral (да-да, тот самый WAT {} + [] !== [] + {})
2) Keywords не являются ключевыми словами, если используются в качестве ключей ObjectLiteral (PropertyName). Например, var a = {for: 1, var: 2}. Более того, следующая конструкция также валидна: a.for + a.var. Вот это действительно WAT! Keyword не является keyword!
3) Ну и конечно hoisting добавил мне пару седых волос на моей юной голове.
+7
Среди начинающих разработчиков часто распространено убеждение, будто бы знание тонкостей языка — это и есть показатель скилла программиста. Во многих компаниях, я знаю, прямо на собеседовании и спрашивают всякую чушь типа всплытия объявлений функций.

Конечно же, к мастерству программирования это всё имеет примерно нулевое отношение. За код, полагающийся на возможность объявить два аргумента с одинаковыми именами в приличной компании погонят несвежими тряпками.

Разумеется, за несколько лет работы тонкости языка всё равно более или менее выучиваются, но это не в коем случае не самоцель и не показатель скилла.
0
Вот тут вы неправы. Хотя я являюсь начинающим программистом, я не считаю, что скилл программиста зависит от знания языка программирования, даже если это С++, тем более если это С++. Или от знания алгоритмов. Это все базовые знания, которые программист усваивает в ВУЗе, до начала своей профессиональной карьеры. И даже при смене языка, хотя бы структуру спецификации или стандарта _крайне_ желательно усвоить, чтобы в случае чего подглядеть, что там да как.
И я ни слова не сказал о скиллах, я лишь говорил о том, что документацию надо знать (вне зависимости от скиллов), по ней надо уметь искать, её надо перечитывать время от времени, в конце концов. Только для того, чтобы не удивляться, когда замена function foo(){} на var foo = function(){} ломает скрипт. Или перенос выражения после return на новую строку ломает скрипт. Или [выберите свой любимый способ выстрелить в ногу]
И да, для тех, кто не знает языка вероятного противника, доступен перевод (про качество перевода не скажу ничего, ибо не читал) es5.javascript.ru Правда, ES6, насколько я знаю, не переведен.
Кроме того, как я уже говорил, стандарт ES очень хорошо написан. Простым и последовательным языком. Прочесть его можно за неделю по вечерам и выходным. Понять? Ну, поэтому я и говорю «перечитывать время от времени». Сколько времени это сыкономит на отладке «за несколько лет работы»? Я не знаю, ибо «документацию надо знать». И если какая-то фигна описана в документации, а программист ее не знает, то ему нужно сказать RTFM и, желательно, раздел, где эта фигня описана.
Но это не всегда спасает от нубских ошибок. Например, попытка изменения строкового литерала, который находится в .rodata. Куда копать при SIGSEGV'e? Ясное дело, надо программисту обьяснить, что такое ELF, что такое Special Segments, что такое .rodata и кинуть в него ссылкой на ELF Format Specification. Ибо не все описано в стандарте С.
Вот что меня поражает, так это то, что, имхо, нормальная ситуация, когда сишники и плюсовики у нас на работе (а других у нас и не водится) свободно объяснят тонкости языка (например, integer promotion (да, это базовое знание С, но никто не гонит ссанными тряпками)), часто с ссылками на разделы стандарта, по вашему мнению, просто немыслима. Это не наезд, а опять же отсылка к RTFM.

Да, я допускаю, что это во мне говорит юношеский максимализм, помноженный на профессиональную деформацию. Мне просто по работе нужно знать и изучать кучу всего, начиная от языка, на котором я программирую, продолжая через знания конкретной архитектуры процессора, для которой моя программа генерирует код (это, естественно, включает в себя знания ассемблера), а также языка программирования, с которого моя программа генерирует код. Кроме того, без знания ядра и системных вызовов мне нечего делать. И я не говорю о оптимизациях, которые, к слову, совсем не просты, хотя и обязательны, ибо «компилятор должен в первую очередь генерировать коректный код, а во вторую — эффективный». И для всего этого есть документация, и чем она полнее, тем лучше для меня. Поэтому стандарты и спецификации для меня на вес золота. И, честно говоря, я обожаю читать и перечитывать плюсовый стандарт перед сном. Так засыпается лучше. Правда, иногда кошмары снятся, но это ничего, терпимо.
0
Оффтопик. Если не секрет, чем вы таким страшным занимаетесь, что одновременно:

Знаете, мне довелось читать много стандартов языков программирования (С, С++, Fortran, EcmaScript, OpenMP, OpenACC, Posix).

Хотя я являюсь начинающим программистом


Помню, много лет назад, когда я уже писал на плюсах больше десяти лет, столкнулся в чистом поле с особо заковыристым шаблоном. И нужно было понять — оно так по стандарту работает, или это фича реализации Microsoft Visual C++ 6.0

Из 1400 страниц стандарта я за несколько дней изучил 50. И не могу сказать, что это было как-то очень уж легко. Несмотря на то, что сами плюсы я знал довольно неплохо.

Конечно, я не самый талантливый программист, но чтобы внимательно прочитать и понять все 1400 страниц плюсового стандарта… Это не на пару дней занятие. И боюсь, даже не на месяц. Хмурая штука.
+1
Довелось читать != прочел целиком и освоил. Сегодня одно, завтра другое. За последние три года прочел только две трети плюсового стандарта (в отличие от того же ES, который я полностью прочел и осознал где-то за пол-года, так как меня заставили^W^W мне нужно было его реализовать). Многие вещи из стандартной библиотеки я даже не трогал. Как понадобится — выделю время. А понадобится либо при затыке, либо при необходимости лезть в компилятор плюсов/стандартную библиотеку. Однако, структура документа мне понятна, к языку (не программирования, а документа) я уже более-менее привык, так что найти что-либо можно будет буквально на несколько минут.
Кстати, вы в курсе, почему нельзя начинать суффикс user-defined-literal'а с чего-либо кроме знака подчеркивания (для действительно пользовательских литералов, а не стандартных)? Ибо хотя грамматика в 2.14.18 говорит, что ud-suffix = identifier, если пройти по ссылке на 17.6.4.3.5, то там буржуйским по белому пишут: «начинать только с '_'», и в 2.14.18 добавляют — ill-formed. На это я наткнулся, когда написал код типа
#define str «thing»
cout << «some»str << endl; // имелась ввиду конкатенация литералов из 2.14.5(13)
а компилятор дал мне отлуп. Говорит, это нифига не допустимый ud-literal.

И да, вы правы, плюсовый стандарт — это один из самых замудренных документов, которые я только читал. Есть там и простые вещи, типа «If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.», так и сложные, типа «Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.».
Но стоит отдать должное, фортрановский стандарт еще никто не смог перегнать по концентрации мути, например, чего только стоит воистину гениальное «Execution of a CONTINUE statement has no effect.» и с трудом понимаемое «Blanks may be inserted freely between tokens to improve readability; for example, blanks may occur between the tokens that form a complex literal constant.» Ну, про пробелы в фортране, я надеюсь, вы наслышаны.

По поводу рода занятий. Все дело в том, что занимаюсь в основном разработкой компиляторов (конечно, пол-года-год назад я участвовал в разработке интерпретатора, но отличий в плане следования стандартам до последней запятой, уж поверьте мне, никаких). Не могу, к сожалению, сказать, что именно я разрабатываю, что принимаю на вход и что генерю на выходе. NDA, сами понимаете.

Но, ИМХО, самая засада это не зубрежка уставов^W стандартов, а ситуация, когда два стандарта пересекаются. Например, OpenACC не описывает взаимодествие с фортрановским кодом не 2003-го стандарта. А мне нужно было добавить поддержку в компилятор, который поддерживает 2008-й стандарт. Разумеется, Самый Простой И Правильный Способ (СПИПС) это дать отлут на такой код. Но голова же дана не только чтобы форменный головной убор носить^W^W^W^W в нее есть, но и для того, чтобы найти Сложный Способ, Который Правильнее СПИПС. Я его, кстати, так и не нашел. До того, как я решил проблему с PARALLEL FOR, меня перекинули на другой проект. Теперь в GCC используется СПИПС.

По поводу начинающего программиста. Если коротко, то профессионально (за деньги) я программирую уже пять лет. До этого еще десять готовил себя к этому. Однако, ИМХО, в компиляторстве я навсегда останусь новичком, ибо сколько бы уставов я не зазубрил, сколько бы оптимизаций не реализовал, сколько бы новых оптимизаций не изобрел, всегда найдется хитрый нюанс, который я не учел, и мой компилятор будет генерировать некоректный код. Если это произойдет завтра, то это выльется милиардными убытками (буквально) для Корпорации, в которой я сейчас работаю, через пол-года. Зато и удовольствие получаешь огромное от работы и удовлетворение. Заказчики — сплошь программисты, требования закреплены и не изменятся, разве что выйдет новая версия стандарта или новый процессор. Ну не вхожу я в ту элиту, которая кидается реализовывать все изменения после очередного драфта. Мне бы свои баги, которые живут годами, поправить.
0
Какого, простите, хрена нарушать нулевое правило программирования (RTFM)?


в отличие от того же ES, который я полностью прочел и осознал где-то за пол-года, так как меня заставили


Я правильно понимаю, что вы предлагаете всем разработчиками js потратить от полугода на чтение стандарта? :). На HTML и CSS тоже по полгода закладывать?
+4
Встречный вопрос: вы все man-pages прочли?

Нет, неправильно вы меня понимаете. Сам стандарт можно прочесть, не особо вдаваясь в суть, пролистывая разделы, с которыми не сталкивались, примерно за неделю по вечерам. Но его нужно прочесть! Это же все-таки не фортрановский стандарт, который требует довольно-таки неплохого знания языка. Затем к ним возвращаться в случае проблем или если уже достаточно поработали с фичами, которые в них описываются.

Например, можно пролистать раздел про automatic semicolon insertion и взять за правило всегда писать этот самый semicolon. По-моему, это правило довольно распространено. Если потом в один день обнаружили, что функция возвращает undefined всесто нужного значения из-за переноса выражения после return на новую строчку, то к нему следует вернуться и прочесть внимательно (этот раздел, ЕМНИП, занимает 3-4 страницы).

К слову, порядок обучения новому языку программирования у меня происходит примерно так — туториалы и книги по языку (начального и среднего уровня), пэт-проект на этом языке, быстрое чтение спецификации (где-то неделя поездок на работу и обратно и дома по вечерам), второй пэт-проект на этом языке. Оба проекта, естественно, относятся к парсингу. Пока что я пишу первый пэт-проект на Clojure. Rust я забросил на время, пока не появится спецификация.

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

Ах да, спасибо PVS-Studio за популяризацию стандартов, и осбенно за статью habrahabr.ru/company/pvs-studio/blog/250701 в коментариях к которой развернулось поистине эпичное обсуждение двух стандартов.

По поводу HTML и CSS ничего не могу сказать. Не знаком.
0
Вы в отделе маркетинга, случайно, не работали?
Такой ведь талант пропадает))
0
За код, полагающийся на возможность объявить два аргумента с одинаковыми именами в приличной компании погонят несвежими тряпками.

Имхо, статья не предлагает этим пользоваться, а наоборот — предостерегает, что на компилятор нельзя полагаться и нужно писать код внимательно и аккуратно.
+1
Сообщество минусует ваш RTFM, потому что к данной статье он не очень уместен.
Для большинства разработчиков чтение стандарта языка не даст ощутимой пользы (а может и наоборот быть вредно, так как бездумное использование всех возможностей, допускаемых стандартом, отнюдь не является признаком хорошего тона). А статья в этом смысле очень полезна — она демонстрирует малоиспользуемые возможности и поясняет, почему они малоиспользуемые.
+1
Художественного произведения — на два-три часа, если интересное. Стандарта языка программирования… Может и на пол года растянутся, если не зайдет.
0
Нет, не очень гигантское. Документация в моём проекте, например, в два раза больше.
Просто стандарт ES6 написан не для людей, а для роботов. Его исключительно тяжело читать, он, фактически, на алгоритмическом языке написан.
0
/me механическим голосом скандирует «Убить всех человеков!» «Убить всех человеков!»
0
> конструктор, принимающий длину, создает массив и задает свойство length, но не создает никаких элементов
Это называется sparce array. Он ещё получится, если удалить что-то: delete arr[1].
-2
А что здесь должно происходить?

var a, b, c;
(a) = 1;
[b] = [2];
({c} = { c: 3 });


стабильный Хром не понимает пока левые части выражений и выкидывает ошибку
0
if (typeof Symbol !== "undefined") {
  // Symbol доступен
}
let Symbol = true; // вызывает синтаксическую ошибку в условии выше!


Вы запутались. Пример для понимания:

{
    typeof Symbol;  // ReferenceError
    let Symbol = true;
}


typeof Symbol;  // boolean

{
    let Symbol = true;
}
+1
В вашем примере отсутствует блочная область, а это как-раз и есть основное отличие:

{
    if (typeof Symbol !== "undefined") {
       // Symbol доступен
    }

    let Symbol = true;
}
0
Во-первых, это перевод и мотороллерпример не мой.

Во-вторых, правильно ли я понимаю, что в глобальной области видимости let работает как-то иначе и ошибки не будет?
0
Проще показать:

{
  var i = true;
}

console.log(i); // true


{
  let i = true;
}

console.log(i); // ReferenceError


Иными словами, инструкция let, позволяет работать работать с блочной областью видимости, как если бы вы писали на С/С++ где такое поведение по-умолчанию.
Вне блока, let ведет себя как инструкция var, за одним исключением циклов (долго спорили на этот счет).

for (let i = 0; i < 10; i++) {
  console.log(i); // ....
}

console.log(i); ReferenceError


Приведу классический пример:

var array = [];

for (let i = 0; i < 10; i++) {
  array.push(() => i);
}

console.log(array[1]()); // 1


Тоже самое с var:

var array = [];

for (var i = 0; i < 10; i++) {
  array.push(() => i);
}

console.log(array[1]()); // 10


Тоже правило распространяется и на такие выражения:

var a = 0;

let(a = 1) console.log(a); // 1

console.log(a); // 0

0
Нет. Это вы запутались



let распространяется и на внутренние блоки.

Вот тут ваш пример корректен, но он не имеет отношения к тому, который в статье:
{
  let i = true;
}

console.log(i); // ReferenceError
+1
Я понял, просто в статье не совсем корректно сформулировано. Под комментарием "// Symbol доступен" имелось ввиду не то, что он реально доступен, а что если код дойдет туда — означает, что он доступен. Скажем, такие ожидания неопытного программиста. Естественно, ошибка выскочит еще на typeof
-3
Ага, только вот неопытные разработчики редко обращают внимания на ошибки.
0
что примечательно, делать return 1, 2, 3; в жс тоже можно.

А вообще — половина пунктов от, пожалуй, непонимания.

(function func(a, a) {  console.log(a)  })
    ("Привет", "Мир"); // выводит "Мир"

Тут — разработчики изначальной спецификации не подумали о том, что разработчики будут так делать.
Сейчас это используется примерно так:

someWeirdAPI.registerCallbackWithArgs(function(_,_,_,_,usefulData){...})


Подчеркивания позволяют повысить читаемость — проще увидеть количество аргументов, которые пропущены.
Ломать обратную совместимость в случае с жс — очень плохая идея, поэтому ввели специальный режим strict.

func(); // func объявлена, но не имеет значения, поэтому ошибка "func не является функцией"
var func = function func() {
  console.log("Всё в порядке");
};

Все верно. В JS есть два типа декларирования переменной: variable (динамический тип) и function. Оба объявления hoist-ятся наверх в первом проходе компилятора (когда объявляются переменные). Function не может быть undefined, поэтому она сразу же регистрируется.

Думаю, так будет понятнее:

func1();
func2();
function func1(){};
var func2 = function(){};

превращается за счет hoist в
function func1(){};
var func2;

func1();
func2();

func2 = function(){};


До ES6 было широко известно, что с помощью оператора typeof можно безопасно узнать, объявлен ли идентификатор, даже если ему не присвоено значение:

if (typeof Symbol !== "undefined") { // Symbol доступен }

if (Symbol !== "undefined") { // Этот код выкинет исключение, если Symbol не объявлен}


Бред. Так никогда не писали.
Начнем с того, что нам нужно узнать, объявлена ли переменная, чтобы с ней можно было работать. В функциях нам это не надо, потому что мы сами их и объявляем, а если и надо — можно воспользоваться блоком try-catch, это крайне редкий кейс.
Если мы работаем в глобальном пространстве — нужно пользоваться 'Symbol' in global<window, например> или .hasOwnProperty()
Typeof дает возможность быстро провериться, но его использование почти всегда скорее мешает, его нужно использовать в двух случаях:
1. определение типа для простых типов (для создания функций с несколькими интерфейсами)
2. быстрая проверка типа объекта при создании API: a instanceof Object не работает, если a взят из айфрейма.

С массивами все тоже очень забавно. Давайте-ка я попробую объяснить, как оно работает.

z = new Array(10);
z[10] = 5;
Object.keys(z)
["10"]


Статья забавная, в общем. Вроде бы и глубокая, а низлежащих механизмов жс-а не затронуто ваще ни разу.
-5
Все высокоуровневые языки (которым является и js), казалось бы, должны избегать концепции «goto»(меток). Интересно, ключевую роль здесь играет обратная совместимость с XX веком?..
+4
Во-первых, все-таки не надо путать goto и break. Второй оператор умеет «прыгать» только вперед и только из внутреннего блока во внешний — что сильно упрощает понимание кода с ним.

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