Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Чем заменить continue (https://javascript.ru/forum/misc/84413-chem-zamenit-continue.html)

Andy_kun 02.09.2022 11:32

Чем заменить continue
 
Подскажите пожалуйста, чем заменить continue для такого кода:
continue - естественно так не работает. Есть ли в JS - аналог оператора goto, который бы так сработал ?

function my_func(numm)
{

   if(numm == 1)
   {
    continue jump;
   }

console.log("check_1");
   if(numm == 2)
   {
    continue jump;
   }

console.log("check_2");    
   if(numm == 3)
   {
    continue jump;
   }   

console.log("check_3");


jump:
console.log("jump");
}



my_func(2);

Vlasenko Fedor 02.09.2022 12:13

https://developer.mozilla.org/ru/doc...atements/label

voraa 02.09.2022 12:32

function my_func(numm){
  jump: {
       if(numm == 1)  break jump;

       console.log("check_1");

       if(numm == 2)  break jump;

       console.log("check_2");  

       if(numm == 3)  break jump;
     
       console.log("check_3");
  } 
 
   console.log("jump");
}
 
my_func(2);

Andy_kun 02.09.2022 12:44

Спасибо!

Aetae 02.09.2022 13:47

Тока за такое руки отрывают и в любых нормальных конфигах оно запрещено.

Andy_kun 02.09.2022 14:04

Цитата:

Сообщение от Aetae (Сообщение 547723)
Тока за такое руки отрывают и в любых нормальных конфигах оно запрещено.

Спасибо за предупреждение, я для себя :)

voraa 02.09.2022 17:22

Цитата:

Сообщение от Aetae
в любых нормальных конфигах оно запрещено.

Конфиги не боги делают.
А людям свойственно ошибаться.
Или выдавать свое частное мнение за Истину.

Aetae 02.09.2022 20:40

Это запрещено по той же причине что и goto - мозголомное запутывание кода. Очень мало людей назовут это ошибкой.

voraa 02.09.2022 21:28

Много, чего можно назвать запутыванием кода.
Тот же break в цикле, разве не подобен goto?
Тот же break в swinch - case разве не служит той же цели - пропустить что то и выйти из блока.

От goto break отличается тем, что передает управление не куда угодно, а просто завершает выполнение блока, подобно, как if () return; завершает функцию.
if () return не запрещен? А то ведь это тоже нарушает парадигму структурного программирования, согласно которой у функции (подпрограммы) должен быть один вход и один выход.

Alikberov 02.09.2022 23:17

Присoeдинюсь к дискуссии.

Лично меня тоже напрягает ограниченность break/continue.
Почему нельзя указать число с указанием уровня вложенности для их действия?
Примерно вот так:
for(i = 0; i < x; ++ i) {
	for(j = 0; j < y; ++ j) {
		for(k = 0; k < z; ++ k) {
			if(k == i)
				continue 1;	// continue 0 / continue - продолжение текущего блока (for k)
							// continue 1 - продолжение блока на 1 уровень выше (for j)
							// continue 2 - продолжение блока на 2 уровня выше (for i)
			switch(m[k]) {
			case false:
				break 2;	// break - выйти из switch
							// break 0 - выйти из текущего цикла (for k)
							// break 1 - выйти из цикла на 1 уровень выше (for j)
							// break 2 - выйти из цикла на 2 уровня выше (for i)
			}
		}
		console.log("Покинули цикл for k");
		if(i == j)
			break 2;		// выходим из цикла двумя уровнями выше (for i)
		switch(m[j]) {
		case true:
			continue 1;		// продолжение блока на 1 уровень выше (for i)
		}
	}
	console.log("Покинули цикл for j");
}

Aetae 02.09.2022 23:21

Alikberov, лол, потому что это запутает код ещё больше. С метками то уже ад, с цифрами - вообще полное безумие.

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


Это тут у тебя три цикла сразу подряд и выполняют полтора действия(и то с полпинка не рабирёшься), а попробуй представить себе реальный цикл с этим дерьмом.

Alikberov 02.09.2022 23:55

Цитата:

Сообщение от Aetae (Сообщение 547729)
Alikberov, лол, потому что это запутает код ещё больше. С метками то уже ад, с цифрами - вообще полное безумие.

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


Это тут у тебя три цикла сразу подряд и выполняют полтора действия(и то с полпинка не рабирёшься), а попробуй представить себе реальный цикл с этим дерьмом.

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

Но, правда: Иногда, в очень узких местах, указание уровня действия не помешало бы, чем вкладывать в цикл функцию с циклом и прерываться по return true/false, типа:
for(i = 0; i < x; ++ i) {
	if(function() {
		for(j = 0; j < y; ++ j) {
			if(i == j)
				return false;
		}
	})
		continue;
}
Что ещё хуже.

Aetae 03.09.2022 00:38

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

voraa 03.09.2022 14:34

Цитата:

Сообщение от Alikberov
Почему нельзя указать число с указанием уровня вложенности для их действия?

Так label для этого и существуют. Не надо вручную считать уровень вложенности.

voraa 03.09.2022 14:46

Вообще в программировании существуют много спорных ситуаций, про которые есть прямо противоположные мнения. Стоит так делать или нет. С одной стороны "удобочитаемость", с другой стороны эффективность.
Это и break, и вложенные тетрарные операции, и использование блоков для инкапсуляции переменных, и обязательное закрытие тегов в html....
Удобочитаемость, как мне кажется - дело привычки и понимания кода.

Доходит до того, что ругань идет по поводу x | 0 для взятия целой части. Мол это не понятно, и всегда надо Math.floor.
А вдруг, кому то не понятно x++? Тогда надо всегда х += 1; использовать? Хотя кому то и это может быть не понятно.
Тогда уж x = x+ 1; И только так.

рони 03.09.2022 14:58

Цитата:

Сообщение от voraa
Доходит до того, что ругань идет по поводу x | 0 для взятия целой части. Мол это не понятно, и всегда надо Math.floor.

Math.trunc()

Alikberov 03.09.2022 15:14

Цитата:

Сообщение от voraa (Сообщение 547734)
Так label для этого и существуют. Не надо вручную считать уровень вложенности.

Нe всегда получается придумать вразумительное имя функции, не говоря уж о метках.:no:
Тем более, когда тело функции синтезируется по шаблону при запуске скрипта.
Цитата:

Доходит до того, что ругань идет по поводу x | 0 для взятия целой части. Мол это не понятно, и всегда надо Math.floor.
А вдруг, кому то не понятно x++? Тогда надо всегда х += 1; использовать? Хотя кому то и это может быть не понятно.
Тогда уж x = x+ 1; И только так.
Для себя я выработал правило писать «for(i = 0; i < n; ++ i) {» вместо «for(i = 0; i < n; i++){», так как «++){» - эзотерика какая-то…

А «x | 0» выглядит не так интуитивно, как «x.0»…:yes:

Тем более, в условиях форума «Math.floor(x)» - слишком громоздкая запись…

Vlasenko Fedor 03.09.2022 15:16

voraa,
x | 0 - неудачный пример для js
Math.floor - работает быстрее и с большими числами
const a = Math.pow(2, 52) / 3;
console.log(a, a|0, Math.floor(a));
alert((a|0) === Math.floor(a))

voraa 03.09.2022 15:55

Цитата:

Сообщение от Vlasenko Fedor
x | 0 - неудачный пример для js

Разумеется, когда это возможно (число в пределах 2**32).
Для меня большие целые числа - экзотика.

Цитата:

Сообщение от Alikberov
не так интуитивно, как «x.0»

Проблема в том, что так нельзя.

Alikberov 03.09.2022 16:19

Цитата:

Сообщение от voraa (Сообщение 547739)
Проблема в том, что так нельзя.

Зa 27 лет JavaScript изменился достаточно хорошо.:yes:
И приобрёл множество экзотических синтаксических особенностей.
Перегрузку операторов до сих пор не ввели.
Думаю, не было бы большой проблемой добавить подобную фишку округления до указанного порядка:
console.log(Math.PI.0);	// 3
console.log(Math.PI.1);	// 3.1
console.log(Math.PI.2);	// 3.14
console.log(Math.PI.3);	// 3.141
console.log(Math.PI.4);	// 3.1415
console.log(Math.PI.5);	// 3.14159
Чем выражение «Math.floor(x * 10 ** n) / 10 ** n» (иногда это требуется)…
(Хотя Фортрановский ** ввели совсем недавно тоже.)

Aetae 03.09.2022 18:11

Это всё херня, я вот жду когда рефы введут.
Что-то типа:
let foo = 1;

function set2(bar*) {
  bar = 2;
}

set2(foo);

console.log(foo) // 2


Вот тогда то всё и сломают полностью.)

Alikberov 03.09.2022 19:24

Цитата:

Сообщение от Aetae (Сообщение 547742)
Это всё херня, я вот жду когда рефы введут.
Вот тогда то всё и сломают полностью.)

В Си это как-то с самого начала было и ничего не поломало.
Хотя, да. Иногда (лично мне) приходилось буквально на ощупь несколько раз переписывать выражение, чтобы всё заработало как надо.:lol:

А «x.0 … x.25» - нигде не встречается и её можно безопасно вводить в спецификацию…

voraa 03.09.2022 19:57

Цитата:

Сообщение от Alikberov
Зa 27 лет JavaScript изменился достаточно хорошо.
И приобрёл множество экзотических синтаксических особенностей.

Ну есть же базовые принципы синтаксиса.
Свойство после "." должно быть задано идентификатором, а не числом или еще чем либо.
Если в x.0 "0" это свойство, то такими же свойcтвами должны быть и любые другие числа (x.1, x.42 .... ) А как на счет x.3.14159?

voraa 03.09.2022 20:05

Цитата:

Сообщение от Aetae
Это всё херня, я вот жду когда рефы введут.

А что, есть такие предложения?
Я вот только слышал про неизменяемые массивы (кртеж, tuple) и неизменяемы простые объекты (record)
Цитата:

Сообщение от Alikberov
В Си это как-то с самого начала было и ничего не поломало.

В С работа с памятью (выделение, освобождение) целиком лежит на пользователе.
А в js рефы и так есть
let x = {a: 0, b: 1}
В х содержится не объект, а ссылка на объект.

Alikberov 03.09.2022 20:18

Цитата:

Сообщение от voraa (Сообщение 547744)
Ну есть же базовые принципы синтаксиса.
Свойство после "." должно быть задано идентификатором, а не числом или еще чем либо.

Ну, так в ES2020 добавили «Nullish Coalescing» и «Optional Chaining», что вообще как-то базовые принципы поломало…:lol:

voraa 03.09.2022 20:44

Это не поломало существующий синтаксис и не привело к синтаксическим неоднозначностям. Просто введены новые операции, задаваемы новыми синтаксическими конструкциями ("??", "?."). Никакие старые синтаксисы и правила при этом не затронуты. Это так же безболезненно, как была введена операция "**"
Никто не будет вводить новую операцию для обращения к свойству, заданному чиcлом, т.к. такая операция уже есть - x[0].

micscr 05.09.2022 06:24

Цитата:

Сообщение от Alikberov (Сообщение 547737)
Для себя я выработал правило писать «for(i = 0; i < n; ++ i) {» вместо «for(i = 0; i < n; i++){», так как «++){» - эзотерика какая-то…

Это у вас очень чудное правило.
Которое больше как фонит тем что вы не разобрались в разнице , мол эзотерика. Нет эзотерики, код для шага цикла ничего не возвращает, поэтому для него нет разницы, и писать ++i несколько паливно

micscr 05.09.2022 07:49

Цитата:

Сообщение от voraa (Сообщение 547735)
Доходит до того, что ругань идет по поводу x | 0 для взятия целой части. Мол это не понятно, и всегда надо Math.floor.

Ну этот трюк также в учебнике на этом сайте не упомянут, видимо ввиду своей неоднозначности.
Я бы его отнес к такому запаху кода как "obscured intent".
В коде у нас побитовая операция, но производим мы не ее, а использует ее сайдэффект по отбрасыванию дробной части и знание что "или" с "нулем" ничего не изменит.

Цитата:

Сообщение от Фаулер
Написать код понятный компьютеру может каждый, но только хорошие программисты пишут код понятный людям.


voraa 05.09.2022 08:30

Цитата:

Сообщение от micscr
В коде у нас побитовая операция,

Это не просто побитовая операция. Это именно предварительное отбрасывания дробной части и приведение числа к 32 битовому целому. Это не сайдэффек, а просто часть операции.
Надо знать все особенности выполнения операции.

Так же как надо знать все особенности ++x и x++ - то, что это не просто прибавление 1 к x
Так же, как знать особенности выполнения операций && и || (то, что логические значения только вычисляются, но не возвращаются)

Человек, читающий код должен знать это. Тогда ему будет понятно.

micscr 05.09.2022 09:51

Цитата:

Сообщение от voraa (Сообщение 547775)
Надо знать все особенности выполнения операции.

Все подробности выполнения побитовой операции полезно знать когда у тебя задача работать с битами, а у нас задача - привести число к целому.
В js почему то так вышло, что везде очень много тонкостей, пример - дока к оператору "==", которые видимо предлагается учить наизусть, когда это твой один язык в стеке, то куда не шло, а иначе ...

voraa 05.09.2022 10:07

Цитата:

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

Что такое n++? Это увеличение n на единицу? Вроде бы да.
Но когда мы пишем m = n++; мы учитываем все особенности этой операции.
Что такое побитовая операция? Если просто так сказать, то можно подозревать, что мы берем битовое представление аргумента (если это вещественное число, то все его 64 разряда м мантиссой и порядком) и работаем с этими битами. Но это не так. Мы же учитываем, что оно сначала преобразуется в 32 разрядное целое.

Что такое логическая операция &&? В фортране или паскале тоже есть логические операции (.AND. и and соответственно). Но если он пришел в js, то стек ни стек, а как выполняется && знать придется. Так же как придется знать, что во что прeобразуется при '10'+1 и при '01' == 1 и при x|0

micscr 05.09.2022 10:28

Не сравнивайте с ++ или &&.
Побитовые операции - очень редкие на самом деле по статистике использования в web стеке, использовать их для других задач - ненужно усложнять код такими низкоуровневыми деталями.
Вон в доках есть более забористые вещи - ~str.indexOf("Widget") - как аналог != -1 , из всего этого можно такую шифрограмму составить, как будто ни Роберт Мартин ни Фаулер никогда и ни для кого своих книг не писали

Aetae 05.09.2022 10:56

Я вот люблю битовые флаги, типа:
const Action = {
  DEFAULT:       0b000000000, // do nothng 
  DELETE:        0b000000001, // to trash
  ARCHIVE:       0b000000010, // to archive
  FINALIZE:      0b000000100, // remove "new" label and star 
  ADD_LABEL:     0b000001000, // add specified label
  READ:          0b000010000, // mark as read
}

...
    return Action.READ | Action.ARCHIVE | Action.FINALIZE;

...
    if(action & Action.ARCHIVE) {
      removeInboxIds.push(id);
    }

Но сейчас такое уже считается сложна, эх...

voraa 05.09.2022 11:08

Используются иногда.
Например в createNodeIterator
https://developer.mozilla.org/en-US/...teNodeIterator

Но чаще в С

Vlasenko Fedor 05.09.2022 12:07

const access = (value, action) =>
  Boolean(
    value &
      {
        read: 1,
        create: 2,
        edit: 4,
        delete: 8,
      }[action]
  );

for (let i = 0; i < 16; i++) {
  let res = [];
  if (i & 1) res.push('read');
  if (i & 2) res.push('create');
  if (i & 4) res.push('edit');
  if (i & 8) res.push('delete');
  console.log(i, res, (i).toString(2).padStart(4, '0'));
}
console.log(access(3, 'edit'));
console.log(access(15, 'delete'));

Редко, но используем, в базах данных с типами set, enum без них никак

Alikberov 05.09.2022 13:55

Цитата:

Сообщение от micscr (Сообщение 547770)
Это у вас очень чудное правило.
Которое больше как фонит тем что вы не разобрались в разнице , мол эзотерика. Нет эзотерики, код для шага цикла ничего не возвращает, поэтому для него нет разницы, и писать ++i несколько паливно

Какaя разница в постинкременте или преинкременте там, где это ни на что не влияет?
А раз разницы нет - есть свобода для проявления индивидуально творческого стиля.
Иногда вообще пишут «I+++j»…:-/

Цитата:

Сообщение от Aetae (Сообщение 547782)
Я вот люблю битовые флаги, типа:
const Action = {
  DEFAULT:       0b000000000, // do nothng 
  DELETE:        0b000000001, // to trash
  ARCHIVE:       0b000000010, // to archive
  FINALIZE:      0b000000100, // remove "new" label and star 
  ADD_LABEL:     0b000001000, // add specified label
  READ:          0b000010000, // mark as read
}

Если идти строго по Си, можно и так:
const	C_Struct = {
	Field_1	:1,	// 1 бит
	Field_2	:2,	// 2 бита
	Field_3	:2,	// 2 бита
	Field_4	:3	// 3 бита
}
var		MyFields = {
	_struct	:C_Struct,
	Fields	:0x9D
}
function Read_CStruct(Struct, Field) {
	var	i = 0;
	for(var id in Struct._struct) {
		if(id == Field)
			return (Struct.Fields >> i) & ~(-1 << Struct._struct[id]);
		i += Struct._struct[id];
	}
}

console.log(`Field_3: ${Read_CStruct(MyFields, "Field_3")}`);

voraa 05.09.2022 16:57

Цитата:

Сообщение от Vlasenko Fedor
Редко, но используем, в базах данных с типами set, enum без них никак

Я бы Boolean(...) на !!(...) заменил :)

Aetae 05.09.2022 18:49

voraa, а я бы нет.)

Vlasenko Fedor 05.09.2022 19:29

Цитата:

Сообщение от Aetae
voraa, а я бы нет

100%
исходный код должен понятен большинству
а там может быть сборщик, минификатор, обфускатор ...

voraa 05.09.2022 20:16

Цитата:

Сообщение от Vlasenko Fedor
исходный код должен понятен большинству

Печально, что большинство такое.... непонятливое

Вспоминается COBOL, где надо было писать MULTIPLY X BY Y.
А что? Всем ведь понятно. X*Y не каждому дано понять.


Часовой пояс GMT +3, время: 16:19.