Я, J = 1 действительно вводит в заблуждение? [закрыто]

11

Существует общий аргумент об инициализации нескольких переменных в одной строке:

Рассмотрим, например, int i, j = 1; что может привести к тому, что некоторые люди ошибочно полагают, что обе переменные инициализируются

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

Однако для этого очень конкретного случая мне интересно следующее: существует ли вообще язык, в котором сам синтаксис i, j = 1 инициализирует обе переменные?

Если нет, то этот аргумент не применяется.

Walfrat
источник
2
Если ваш язык вменяемый, потенциальная путаница безвредна, потому что доступ к неинициализированной переменной вызывает ошибку компилятора.
CodesInChaos
4
@CodesInChaos вы говорите, C не вменяемый?
Балдрикк
2
То, что язык что-то позволяет, не означает, что вы не причиняете людям ненужную боль. Единственное место, куда этот код требуется, - это во время викторин, предназначенных для наказания тех, кто не запомнил языковую спецификацию. Я всегда терпел неудачу в таких вопросах. BLEH.
candied_orange
2
В Visual Basic 6 Dim Apple, Orange, Pear as Fruitесть юридическая декларация. Предположим, вы не знаете VB. Ваше первое впечатление такого Appleтипа Fruit? Это не так. Помните, что языки часто читают люди, которые не являются экспертами в этом языке; если вы являетесь экспертом, используйте язык с умом, чтобы четко сообщать о своих намерениях даже неспециалистам. Я никогда не использую множественные инициализации на любом языке.
Эрик Липперт
13
Точно так же: рассмотрим var x = 1, y = 1.5; Это так же, как int x = 1; double y = 1.5;или это так же, как double x = 1, y = 1.5;? Когда мы добавили varC # 3.0, я провел опрос и обнаружил, что около половины людей считают, что первое «очевидно» правильно, а другая половина считает, что другое «очевидно» правильно, и поэтому мы сделали его незаконным. Функция, которая вводит в заблуждение половину населения, является плохой функцией.
Эрик Липперт

Ответы:

37

Я думаю, что нет, но это не главное. Дело в том , что i, j = 0очень легко перепутать i = j = 0, что делает инициализации обоих. Ясность является наиболее важным требованием к исходному коду рядом с корректностью, и тот факт, что этот вопрос даже возникает, доказывает, что ясность является субоптимальной.

Килиан Фот
источник
3
Я также утверждаю, что если такое утверждение не инициализирует оба утверждения, почему оно вообще существует?
Берин Лорич
2
@BerinLoritsch зависит от языка. Это часто делается в JavaScript из-за поднятия декларации: многие считают, что лучше объявлять переменные в верхней части области, в которой они доступны, даже если вы не инициализируете их до тех пор, пока они не будут использованы в коде. , Почти все инструменты преобразования кода выводятся таким образом.
Джаред Смит
1
Я полагаю, это одно, если инструмент вывода кода сделал это, так как это должно быть доверенным. Однако для людей я бы рекомендовал не объединять объявление и инициализацию последнего элемента только в одну строку. Это похоже на ошибку, ожидающую своего появления.
Берин Лорич
2
@JaredSmith Помимо Maple, я не могу придумать язык, для которого в данный момент это желательно, даже C теперь предпочитает ближе к области видимости (например, C ++ и большинство других языков с наполовину приличными статическими компиляторами), потому что это дает преимущество в устранении потенциальных ошибок и позволяет компилятор сам решает, что делать с переменной, если функциональность не меняется, что потенциально позволяет улучшить оптимизацию, учитывая, что вы можете избежать использования меньшего количества регистров.
августа
6
Независимо от языка, следует спросить: «В чем польза письма int i, j=1от int i; int j = 1(или даже лучше, отдельных строк)?»
chepner
2

Я думаю, вы можете поспорить за любую сторону:

  • Контра i, j = 0:
    Математики используют это, чтобы означать, что оба iи jдолжны быть равны нулю.

  • Pro i, j = 0:
    Это просто вопрос знания приоритетов ваших операторов. И если вы сомневаетесь в их приоритете, сейчас самое время посмотреть на него.

    Это та же самая причина, почему мы пишем вещи a.b += c[i]*d[i];без скобок. Конечно, это эквивалентно (a.b) += ((c[i])*(d[i]));, но можно ожидать, что программисты будут знать наизусть приоритет наиболее часто используемых операторов и смогут искать приоритет операторов, когда они не уверены. Таким образом, круглые скобки, как правило, считаются бесполезным беспорядком, если только они не приводят к другому порядку оценки, который предписывает приоритет оператора.

    Конечно, есть исключения. Приоритет <<и, +как правило, считается достаточно неоднозначным, чтобы избежать скобок в любом случае. Но это исключение, которое подтверждает правило.

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

cmaster - восстановить монику
источник
7
Отмечу, что в int i, j = 0;нем нет операторов . Единственное выражение в этом утверждении - 0и, следовательно, приоритет оператора не входит в него. Парсер не ,считается оператором запятой или =оператором присваивания; скорее это грамматические части заявления декларации.
Эрик Липперт
@EricLippert Что касается правил предшествования, это различие не имеет значения: любой известный мне язык стиля C использует те же приоритеты в объявлении, что и в других выражениях. Что-нибудь еще пригласило бы несчастье.
cmaster - восстановить монику
but programmers can be expected to know the precedence of the most used operators by heart, ты говоришь. В приведенном вами примере я не уверен, что большинство (средних) программистов воспринимают оператор доступа к элементу или оператор индекса массива как операторы в математическом смысле, но вместо этого считают их скорее существительными естественного языка и умножением оператор как глагол. Вот почему int i, j, k = 0;такая извергательная конструкция, потому что она представляет собой аналог естественного языка: «int-переменные i, j и k объявлены и должны быть установлены в 0»!
Стив
@Steve Как вы помните правила предшествования как программист, полностью зависит от вас. Если это поможет вам думать о них как о существительных языка, сделайте это. Тем не менее, в этом случае вы столкнетесь с проблемами, когда увидите такие вещи, как *a[i]я, я не думаю, что вы сможете в достаточной степени разобраться с аналогией с «существительными». Что касается int i, j, k = 0;, это может означать что угодно, если вы не ищите правила: третье толкование было бы объявить int i, затем оценить jи, наконец, назначить k = 0. Если вы не знаете синтаксис вашего языка, вы не сможете разобрать такие конструкции. Это ваша проблема, если вы все равно это сделаете.
cmaster - восстановить монику
@cmaster, я не выражал свою конкретную стратегию запоминания, ха-ха. Я не программист на Си, поэтому мое знакомство с приоритетами операторов в Си второсортно. Но когда я посмотрел на ваш пример, я заметил, что я даже не думал о том, что оператор умножения имеет относительный приоритет перед оператором индекса массива. То есть я не читал a[i]как примененный к нему оператор индекса a, а скорее читал оба вместе как неприводимый синтаксический элемент, определяющий операнд оператора умножения, и, таким образом, мне даже не предлагалось оценить приоритет. (1/2)
Стив