Здравствуйте, vsb, Вы писали:
N>>Ну вот почему-то ты сделал такое разделение. А другой скажет, что параметр функции — такая же локальная переменная, но автоматически присвоившая значение на входе. И я не вижу, чем один вариант существенно обоснованнее другого. Мне тоже _чуть-чуть_ было бы удобнее видеть, что параметры неизменяемы, но я не могу найти этому обоснования и не вижу силы за твоим обоснованием.
vsb>Все мои предпочтения это исключительно opinionated, как говорится. Я кодирую в своих предпочтениях настолько строгий стиль кодирования, насколько это разумно в рамках синтаксиса языка. Конечно нет ничего сакрального в неизменяемых параметрах. Просто мне так кажется правильней. Изменяемые переменные должны быть нужны редко. Но не настолько редко, чтобы от них отказываться, иначе это уже что-то вроде хаскеля со своей историей, как говорится.
Ну вообще всё семейство ФП. Я на Эрланге много писал. Неизменяемые переменные его стиля это, конечно, красиво. Но иногда они превращаются в жуткий геморрой. То надо передавать 50 изменяемых значений в функцию, рекурсивно... — приходится передавать одну большую мапу со значениями. То простейший цикл уже не напишешь без рекурсии. В тяжёлых случаях коллеги вообще переходили на словарь процесса (в его контексте это грубость, как в C++ кастовать указатели между несвязанными классами и ходить по смещению от них).
Вот честно, больше не хочу такого. Тут согласен, что их надо оставить.
Но это мало связано с вопросом, какое умолчание лучше. Надо наблюдать.
vsb> mutable параметры нужны ещё реже и от них уже отказаться можно, т.к. всё же это семантически немного другая сущность
Ну вот насколько это "немного", достаточно ли его для другой политики — ХЗ.
vsb> и то, что они в большинстве языков программирования тождественны локальным переменным, это просто такая мода. Никаких проблем такой отказ не несёт, просто человек объявит лишнюю переменную. Может даже у этой лишней переменной будет более удачное имя.
Про имена это к Swift — там у параметров разделяются внутренние и внешние имена — и это правильно.
N>>>>Во всём коде функции используется kptm2, в одном месте kmpt2. Удачи в поиске. Особенно в конце спринта с рычащим тимлидом.
vsb>>>Если это неизменяемая переменная, то второе место не скомпилируется.
N>>Кто из этих двоих переменных "это"?
vsb>Немного не то сказал. Мой поинт в том, что неизменяемой переменной ты не будешь на ровном месте присваивать новое значение. Т.е. ты не будешь писать код kptm2 = 1; ...; kmpt2 = 2; print(kmpt2). Ты вернёшься на место объявления kptm2 и напишешь mutable kptm2 = 1; ...; kmpt2 = 2; print(kmpt2) к примеру. И вот этот пример уже выдаст ошибку — mutable переменная не была изменена.
Эээ.
1. А с чего бы это сразу объявлять ошибкой? Ну mutable, ну не изменена.
(На самом деле тут ещё один вопрос, конечно. Имеет смысл по умолчанию делать, что ситуации типа "присвоенное значение не используется" создают ошибки. Как минимум в release-сборке, если использовать это деление. Но есть же автоматическая генерация кода. Надо иметь возможность контекстно-локально отключать такие ошибки.)
2. Но представь себе, что kmpt2 написано дважды вместо kptm2 в разных местах. Это тоже вероятно. Всё, твой контроль по принципу единичности — уже не сработает. Контроль по неиспользуемости присвоенного значения — может сработать, а может и нет — в зависимости от интеллекта компилятора.
Ну и см. ниже про типы.
Опциональную политику такого объявления по первому присвоению я бы понял. Тотальную — нет. По умолчанию — тоже нет. Даже для Хаскеля
vsb>Если эта переменная изначально была mutable и ты опечатался в низу функции и случайно завёл новую переменную, тут ничего не сделать, будет баг, да.
Ну вот да — контроль тут будет, мягко говоря, слабым.
vsb>Но исходя из предположения, что в современном языке изменяемые переменные это чуть ли не дурной тон, нужно использовать по максимуму приёмы функционального программирования, я полагаю, что эта ситуация не будет настолько частой, чтобы это вызывало на практике проблемы.
Надо смотреть на практику Питона, где эта диверсия по умолчанию.
vsb>Я считаю, что есть большая ценность в том, чтобы убрать визуальный шум от объявления неизменяемой переменной, т.к. этот шум читателю кода ничего не даёт.
Хм.
Раньше я был категорическим сторонником стиля "чем меньше букв, тем лучше". А потом начал активно смещаться в сторону того, что некоторая избыточность крайне полезна. Не, например, begin-end вместо {}, это уже перебор, а, например, "var x: int", а не "var x int", как в Go. Обязательны слова типа var, function (даже если сократить до fn, как сейчас модно), и вообще стиль объявлений Pascal / Go / (самый новый) C++ с auto и ->, чтобы не плодить Most Vexing Parse. Ну и прочее. Набирать не сильно больше, а пользы — вагоны.
Так и тут — если ты напишешь "let kptm2 = foo()", или "kptm2 := foo()", как в Go с его присвоением-с-декларацией, а не "kptm2 = foo()", это будет совершенно минимальная добавка, зато исключит массу проблем.
N>>"Что-то сильно не так делаешь" это слишком абстрактный аргумент, чтобы иметь хоть какую-то силу. Нужно, чтобы ситуации не происходило вообще, или в крайне малом количестве случаев.
N>>А учитывая, что объявление переменной ещё и (обычно) должно задавать её тип (кроме случаев, когда ты явно разрешил компилятору автовывод типа) — то за аргументы за автосоздание переменной уходят в область бесконечно малых.
vsb>Автовывод типа это уже давно стандарт де-факто почти во всех языках и подразумевается сам собой.
Да вот не совсем. Ты смешиваешь два автовывода — автовывод по инициализации и автовывод по всему использованию.
Первый — удел процедурных языков. Второй — группы *ML/Haskell/etc.
Но это уклонение от вопроса, потому что:
vsb>Все типы локальных переменных выводятся и это не опционально.
Ну да, ещё скажи, что ты не можешь сказать "int x" для локальной переменной, только "var x"

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