Rust: ключевое слово var только для изменчивых местных жителей

Созданный на 20 июн. 2012  ·  35Комментарии  ·  Источник: rust-lang/rust

В выпуске № 1273 предлагается let mut для изменяемых локальных переменных и mut для изменяемых полей. let mut более подробен, чем одно ключевое слово, а также нарушает выравнивание столбцов. Людям справедливо не нравилась идея var для объявления изменяемых полей. Но я думаю, что никто не предлагал использовать var для изменяемых локальных объявлений и mut для объявлений изменяемых полей:

let x = 7; // declaration of immutable variable x
var y = 7; // declaration of mutable variable y
type point = { mut x: int, mut y: int }; // declaration of mutable record type

Дэйв

I-nominated

Все 35 Комментарий

Должен признаться, сначала я подумал, что мы должны использовать одно и то же ключевое слово для изменяемых переменных и изменяемых полей, но var неплохо читается (хотя мне не нравится let mut )

Я думаю, что объявление изменяемой переменной немного сложнее, чем неизменяемая. Я вижу, как программисты используют просто «var» для «согласованности» или потому, что «var» будет более мощным (не нужно менять его, если вы решите изменить позже). Тогда вы получите менее читаемый код в целом.

Я не предполагаю, что Rust должен быть серьезным языком рабства и дисциплины, но мягкий толчок в правильном направлении, я думаю, морально оправдан (т. Е. Правилом было бы «для безопасного кода более безопасные конструкции должны быть менее шумными, чем более мощные, но конструкции, которые проще испортить ").

С одной стороны, мне это нравится, так как это устранит визуальную двусмысленность этой формы:

let mut x = 4,
    y = 8;  // is y mutable or not?

Но я склонен встать на сторону ssylvan. Объявление изменяемых объектов не обязательно должно быть _ugly_, но я думаю, это имеет смысл, если их создавать немного менее удобно, чем неизменяемые, хотя бы одним нажатием клавиши. Ключевое слово активации также должно быть отличительным, и (IMO) var слишком широко используется в качестве ключевого слова объявления общей переменной, чтобы специально передавать изменчивость на языке, который гордится неизменностью по умолчанию. И подумайте о бедных программистах на C #, для которых var - это наш let !

Мне все еще нравится идея заменить let mut одним ключевым словом, чтобы обратиться к приведенному выше фрагменту кода, но есть ли причина для введения нового ключевого слова, когда будет достаточно mut , согласно исходное предложение №1273?

@pcwalton указал на проблему с простым использованием mut : существует неоднозначность с литералами записи и выражениями блоков, для решения которой требуется произвольный просмотр вперед.

{ mut x: int ...

Запись литерала или блока с локальной переменной?

Я видел, как многие программисты просто узнали, что var - это то, как вы объявляете переменные в Rust, а не использовали let вообще. В конце концов, var - это то, как вы объявляете локальные переменные в таких языках, как JavaScript. Я склонен думать, что это хорошее предложение.

Я слышал вчера, как кто-то указал, что теперь let и var будут иметь одинаковую длину, что было бы неплохо для выравнивания.

Я несколько равнодушен, но предпочитаю var , потому что он короче. Я считаю, что делать изменчивость раздражающей - нежелательная цель. (На самом деле, я склонен думать, что роль языка программирования не должна заключаться в том, чтобы делать что-либо раздражающим - просто _clear_, что не одно и то же.)

Хотя я все еще опасаюсь использовать let и var вместе (точно так же, как Javascript, но на 100% разные), было бы гораздо меньше проблем, если бы был проход lint для обнаружения переменных. которые объявлены как изменяемые, но никогда не изменяются.

Есть план сделать изменчивость частью типа. Влияет ли это на местных жителей и делает ли это неактуальным?

Как насчет:

val x = ... // immutable (val-ue)
var y = ... // mutable (var-iable)

Как в Scala.

Я думаю, что @brson прав, и эта проблема исчезнет, ​​как только мы переместим mut в тип, т.е. вы получите let x = mut 10;

Закрытие этого вопроса на данный момент; открой заново, если думаешь, что я ошибаюсь!

Я не уверен в этом. Мне нравится идея перенести mut в этот типаж, но я не знаю, что это «сделка решена» - в этом может быть сохраняющаяся странность. В любом случае, я никогда не думал, что можно написать let x = mut 5 , я всегда предполагал, что вы напишете let mut x = 5 точно так же, как сегодня; "изменчивость" типа переменной зависит от способа ее объявления, а не от присвоенного ей значения.

В противном случае может показаться, что если у вас есть массив x типа [mut int] и вы пишете let y = x[0] тогда y является изменяемым? Или что-то? Это кажется нежелательным.

@Dretch Я не люблю val / var, потому что они недостаточно различимы, хотя прецедент Scala хорош.

Я разделяю озабоченность @eholk по поводу того, что люди учатся использовать var по умолчанию. Как это работает сейчас, я обычно объявляю все неизменным, затем компилятор напоминает мне, что это должно быть изменяемым, затем я набираю mut . Это, пожалуй, хорошее поведение, к которому вы были бы менее склонны с разделением var/let - набирать var и let одинаково сложно, но вы даже не можете ввести let mut без ввода let .

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

@nikomatsakis В частности, мне

Я склонен согласиться с @pcwalton, что мы не должны наказывать программистов за использование изменяемой привязки, если они этого хотят. Что касается опасений по поводу того, что люди без необходимости используют var , мы могли бы добавить необязательное предупреждение, которое жалуется, если привязка var назначается отдельно. Но я также думаю, что мы можем создать прецеденты для хорошего стиля в rustc и стандартной библиотеке.

Дэйв

Неужели это так ужасно, если программисты объявляют все свои переменные изменяемыми? Похоже, что это еще не конец света, если у нас есть набор программистов на Rust, которые просто думают, что var - это то, как вы объявляете переменные, и другой набор, который понимает, что большую часть времени использует let и var при необходимости. Как первые программисты на Rust, мы можем создать прецедент в пользу правильного использования let и var .

ИМХО хороший синтаксический дизайн - это не просто «все», что вы когда-либо захотите сделать удобным, это мягкое подталкивание людей к «гладкому пути» семантики языка и целей дизайна.

Например, вы, вероятно, не стали бы добавлять специальную синтаксическую поддержку для связанных списков в Rust (а-ля Haskell), потому что один из основополагающих принципов Rust - быть эффективным, и повсеместное использование связанных списков будет работать вопреки этому принципу. По той же причине совместное использование изменяемых данных между потоками, вероятно, не должно быть слишком удобным (поскольку безопасный параллелизм - это еще один принцип), и при этом не должно быть очень удобно приводить произвольный int к указателю (поскольку безопасность памяти - важный принцип).

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

Изменяемые (локальные) переменные далеко не так плохи, как любая из них, но если Rust действительно отдает предпочтение неизменным данным из соображений корректности и обслуживания (с чем я лично согласен), то синтаксис в идеале должен слегка подталкивать в этом направлении. Даже одного дополнительного символа или дополнительной сигилы-модификатора или чего-то еще будет достаточно, чтобы прояснить, что «let» менее сложна, чем «let mut» или «let!». или что-то еще, и, следовательно, это должно быть предпочтительное значение по умолчанию, которое вы должны попробовать, когда вам на самом деле не нужно, чтобы переменная была изменяемой.

@ssylvan О, я понимаю это, это просто вопрос степени и баланса компромиссов. Мы уже продвигаем неизменность структур данных, и неизменные локальные переменные IMO менее важны для продвижения, чем неизменяемые поля. (Тем более, что в IINM мы не позволяем изменяемым локальным переменным сбегать в закрытии кучи.) И потеря возможности рефакторинга между let и var без изменения количества столбцов перевешивает преимущества продвижение неизменных местных жителей. Трудно определить количественно, так что я думаю, это просто мое ощущение.

Дэйв

Что ж, в этом случае, по крайней мере, «let foo = mut bar» или «let foo: = bar» вместо «let mut foo = bar» составят первую строку токенов. Предположительно имя переменной будет переменной длины, поэтому не так важно избегать дополнительных модификаторов в остальной части оператора.

О, эй, я неравнодушен к идее := .

Дэйв

Если подумать, Паскаль навсегда не крут. Беру обратно. :)

Дэйв

Кроме того, let foo := bar предотвращает что-то вроде этого:

let mut foo;
foo = bar;

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

@eholk Я не думаю, что это

Дэйв

Что касается := , Go использует его для обозначения присваивания с выводом типа (хотя это еще не совсем основной язык). Но я могу предвидеть трудности с разграничением двух форм с первого взгляда:

let foo = "hello";
let foo := "hell";

Аргумент brson в пользу текущего синтаксиса (т. е. что изменяемое объявление сначала требует неизменяемого объявления) убедителен. Совершенно здорово, если языки программирования самоуверенны, если только они не придурки. :)

Не интересует = vs. := . В основном в отличие от val , var и их вариаций; просто не очевидно, что он контролирует изменчивость. Я имею в виду, что я не уйду с отвращением, если мы воспользуемся одним из них, но я думаю, что «необходимость объяснять мнемонику» - плохой знак. Меня больше устраивает:

  • Позволить типу диктовать это.
  • Разрешение только mut работать в качестве локального декларатора и требует, чтобы синтаксический анализатор откладывал фиксацию синтаксиса записи по сравнению с локальным объявлением одного дополнительного токена; он по-прежнему LL (1) просто добавляет дополнительное промежуточное состояние грамматики, без дополнительного возврата (допустимы оба пути вперед).
  • Оставляем как let mut .

Основная причина избегать «случайных» изменяемых локальных переменных заключается в том, что мы ввели захват среды, поэтому они превращаются в форму действий на расстоянии, а также опасности для различных анализов, таких как заимствование.

(Все let были изначально изменяемыми, но у нас также не было захвата среды, только привязка. Теперь у нас нет привязки, только захват env. Tomayto, tomahto.)

Я считаю, что сейчас изменяемые объекты не могут быть неявно захвачены.

@graydon правильно, что было две исходных мотивации. Однако по-прежнему актуален только один. Две мотивации были

  • неявный "копированием" изменяемых переменных в fn@
  • понимание того, какие данные изменяемы, а какие нет

Оказывается, последнее уже не актуально. Использование изменяемых / неизменяемых переменных было слишком грубым на практике, поэтому у заимствования есть идея заимствовать переменную «временно» - изменяемая переменная может быть заимствована с неизменяемым ptr, пока переменная не изменяется, пока указатель находится в сфера.

Возможно, мы могли бы просто удалить идею изменяемых / неизменяемых локальных переменных и вернуться к старому правилу - все изменчиво. Затем мы могли бы выдавать предупреждения, когда переменная, неявно копируемая в замыкание, изменяется после создания замыкания.

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

@Dretch Мне также нравится стиль Scala с ключевыми словами val и var.

Мне нравится, как текущий синтаксис заставляет изменяемые элементы торчать, как больной палец; это упрощает сканирование кода. val и var кажутся в этом отношении слишком визуально похожими. Это не означает, что изменяемые переменные абсолютно _должны_ выделяться, но сохранение визуальной отличимости ключевых слов является важным аспектом удобства использования.

Я так понимаю, что изменяемые поля будут удалены из ржавчины. Значит ли это , что mut может затем быть использован вместо let mut , потому что двусмысленность записи / переменной на блок исчезнет?

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

@Dretch - это правда, что изменяемые поля уходят, а структурные записи уже ушли.

Я в основном безразличен к этой проблеме, хотя хотел бы отметить, что _ может_ иметь смысл, чтобы mut самостоятельным ключевым словом объявления (как предлагает Дретч) в случае замораживания / оттаивания . Сравните сегодня:

let foo = 1;  // immutable
/* 10,000 lines of code here */
let mut foo = foo;  // we're making foo mutable, totally understandable
/* 10,000 lines of code here */
let foo = foo;  // potential wtf

С предложением:

let foo = 1;  // immutable
/* 10,000 lines of code here */
mut foo = foo;  // a mutable foo, no problems here
/* 10,000 lines of code here */
let foo = foo;  // slightly less of a potential for wtf, since we officially have two declaration forms

Хотя я также чувствую, что это сделало бы Rust-ism «отсутствие mut подразумевает неизменность» менее последовательным, потому что мы все равно будем писать let foo = 1; а не просто foo = 1; (последняя форма, очевидно, нежелательно для декларирования).

Kotlin также использует val и var .

Я не думаю, что мы собираемся вносить это изменение, но я номинирован на этап 1, четко определенный, чтобы мы могли его уладить.

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги