Это проблема дополнительного отслеживания для RFC «Уточнение и оптимизация путей и видимости» (rust-lang/rfcs#2126).
рассматривая вопрос о crate
как модификаторе видимости.
Нерешенные вопросы:
struct Foo(crate ::bar)
?Комментарии о crate
как модификаторе видимости:
pub(extern)
вместо этогоЛично я очень поддерживаю crate
в качестве модификатора видимости и делюсь здесь комментарием @stepancheg . Я думаю, что мы должны поощрять меньшую и более строгую видимость, и crate
делает именно это.
Я лично не против написать pub(crate)
, намерение кажется очень явным.
Пример, приведенный @johnthagen , действительно больно видеть (используя crate
):
use crate::menu::{Sound, Volume};
crate mod color;
...
/// A type for storing text and an associated color it should
/// be drawn as.
crate struct ColoredText {
crate color: types::Color,
crate text: &'static str,
}
crate mod color;
особенно кажется запутанным, вам определенно нужно немного подумать о том, что там происходит.
Некоторые из этих примеров очень похожи на C static
esque-, но на самом деле удивительно различны.
Пример из-за @johnthagen мне не кажется плохим. На самом деле, это читается естественно, и мне очень нравится симметрия. В каком-то смысле это красиво.
Если читабельность:
crate struct ColoredText {
crate color: types::Color,
crate text: &'static str,
}
становится проблемой; затем IDE/редактор, понимающий синтаксис Rust, может выделить токены crate
в разных позициях разными цветами. Это должно хорошо прояснить разницу, я думаю.
crate
как модификатор видимости определенно странный: он использует очень специфичное для ржавчины ключевое слово для вещи, которая не специфична для ржавчины. Kotlin и C# используют для этого internal
.
Я лично хотел бы повторно использовать pub
для crate-visible
и использовать более кричащий синтаксис для видимого мира, например pub*
или pub!
.
Это поднималось раньше, но я думаю, что коренные проблемы, которые я вижу, следующие:
crate
— существительное . Я думаю, что pub(crate)
выглядит длинным и странным, поэтому я полностью поддерживаю замену его на что- то , но с ним действительно было связано общедоступное прилагательное, поэтому грамматически оно выглядело лучше.crate
теперь используется в качестве привязки для импорта «этого ящика», что означает нечто иное, чем «где бы это ни было определено, оно также явно экспортируется из этого ящика».// Here `crate` means the root of this crate.
use crate::menu::{Sound, Volume};
// Here, `crate` means: export crate::game::color
// The `crate` is referring to `color`, not the root.
crate mod color;
...
/// A type for storing text and an associated color it should
/// be drawn as.
// Same potential confusion as `crate mod color`
crate struct ColoredText {
crate color: types::Color,
crate text: &'static str,
}
По сравнению с примером использования @matklad internal
из Kotlin/C#.
use crate::menu::{Sound, Volume};
internal mod color;
...
/// A type for storing text and an associated color it should
/// be drawn as.
internal struct ColoredText {
internal color: types::Color,
internal text: &'static str,
}
Я не говорю, что internal
— правильное ключевое слово (Rust любит очень короткие аббревиатуры, а int
, к сожалению, полон путаницы с C/C++/Java), но лично я думаю, что второй пример сразу читабельнее.
Я также думаю, что ключевое слово видимости crate
будет сбивать с толку людей , перешедших на Rust с других языков. Если даже многие из нас, достаточно вовлеченных в Rust, чтобы комментировать эти темы, будут возмущены, я должен представить, что это столкнет с толку и людей, плохо знакомых с Rust.
Немного более длинный синтаксис pub(crate)
может не иметь большого значения, если бы не становился предупреждением/ошибкой наличия элементов pub
, недоступных за пределами ящика. Я лично хочу, чтобы, если бы у меня был pub(crate) struct Foo { ... }
, компилятор мог бы понять, что все pub fn
в impl Foo
явно недостижимы, и не беспокоить меня по этому поводу.
Я считаю, что в настоящее время в Rust 2015 это просто занятая работа, если я когда-либо отмечаю тип от pub struct Foo
до pub(crate) struct Foo
, как компилятор затем кричит во всех местах, где какой-то другой pub fn
s существуют с использованием внезапного типа pub(crate)
, когда проблема не реальна, потому что другой тип также pub(crate)
.
Я также нахожу идею @matklad перепрофилировать pub
как общедоступный ящик и использовать export
или что-то в этом роде для экспорта, видимого миру. Но может быть, это слишком большое расхождение для издания?
Перед текущей версией предлагалось перепрофилировать pub
как crate-public и добавить новую видимость для world-public. Такое изменение существующей семантики было сочтено слишком радикальным даже для редакции, поэтому pub
теперь сохраняет свое текущее значение.
Мне кажется, меньше обсуждалось и рассматривалось перепрофилирование pub
исключительно с помощью lint. Возможно, мы могли бы переключить lint с «предупреждать о pub
, которые недоступны за пределами ящика» на «предупреждать о pub
, которые доступны за пределами ящика», и добавить совершенно необязательный pub(extern)
/ export
ключевое слово. То есть не меняйте никакой семантики, просто добавьте синтаксис подавления ворса.
Я подозреваю, что это будет менее разрушительным, исходя из предположения, что общедоступных в мире элементов меньше, чем общедоступных в ящиках. Это также сохранило бы интуитивное (хотя и немного неправильное) значение pub
как «экспорт из текущего модуля», вместо того, чтобы показывать всем истинное поведение видимости.
Rust любит очень короткие аббревиатуры, а
int
, к сожалению, полна путаницы с C/C++/Java.
FWIW, хотя он сохраняет только два символа, если бы мы хотели сократить internal
, «правильной» аббревиатурой, вероятно, по аналогии с extern
al было бы intern
. К сожалению, это также существительное с общепринятым, другим значением. Ну что ж.
@glaebhoerl intern
— хороший вариант! ❤️
Симметрия с extern
действительно хороша, и IMO значительно уменьшит потенциальную путаницу с формой существительного intern
.
Он короткий (всего на 1 символ больше, чем crate
) и не конфликтует с use crate::
.
Обновленный пример будет выглядеть так:
use crate::menu::{Sound, Volume};
intern mod color;
...
/// A type for storing text and an associated color it should
/// be drawn as.
intern struct ColoredText {
intern color: types::Color,
intern text: &'static str,
}
Я упоминал об этом раньше, но я не уверен, в чем проблема с существительными, используемыми в качестве прилагательных?
Напомним: существует множество существительных, которые можно использовать в качестве прилагательных, например. домашняя кошка, компьютерная мышь, компьютерный стол и т. д. Поиск в Google _английских существительных, используемых в качестве прилагательных_, кажется, указывает на то, что нет ничего изначально неправильного, хотя не все существительные работают как прилагательные.
Давай попробуем:
_crate mod hello;_ Модуль ящика с именем hello, чувствует себя нормально.
_crate fn world() {}_ Функция ящика с именем world работает нормально.
_crate struct Foo;_ Структура ящика с именем Foo чувствует себя нормально.
_crate enum Bar {}_ Crate enum с именем Bar, все в порядке.
_Черта ящика Баз {}_ Черта ящика по имени Баз, чувствует себя хорошо.
_crate use self::local::Foo;_ Ок, это не работает, использовать crate? Вы можете прочитать это как полезный предмет из ящика с именем Foo. Это ломает шаблон.
Это также может быть неудобным при использовании перед членами структуры и даже больше в сочетании с crate в качестве корня пути.
Хотя ящик не идеален, я не уверен, что «быть существительным» является решающим фактором.
Проблема в том, что это очень редко. Я не знаю ни одного языка программирования, который использует существительные в качестве модификатора типа.
@Центрил
становится проблемой; затем IDE/редактор, который понимает синтаксис Rust, может выделить токены ящика в разных позициях разными цветами. Это должно хорошо прояснить разницу, я думаю.
Лично я нахожу функции различных редакторов приятными, но не думаю, что нам следует разрабатывать язык, исходя из предположения о достаточно продвинутом редакторе. Я чувствовал, что C# был разработан таким образом, и это было основным фактором моего разочарования в этом языке.
@epage Я думаю, что crate
в качестве модификатора видимости — хорошая идея, независимо от выделения; Я просто предполагаю, что выделение является дополнительным смягчением. В частности, для любого редактора должно быть довольно тривиально выделять crate::
иначе, чем crate field
, потому что первое всегда равно crate
+ ::
, что легко проверить. for во всех случаях, кроме crate ::foo::bar
(но это будет довольно редко..).
Как человек, работающий с IDE, я думаю, что такое выделение добавит значительное количество шума к очень небольшому объему информации, что приведет к отрицательному результату. IMO (это очень личное, но основанное на использовании и внедрении мощных IDE) выделение лучше всего работает, когда оно передает семантическую нелокальную информацию (относится ли это использование к переменной, которая была объявлена с помощью mut
) и подчеркивает локальные «стандартные» аспекты кода (поэтому все ключевые слова должны иметь одинаковый стиль).
Мне кажется, что dom
(то есть: внутренний) является потенциальным кандидатом.
Он состоит из трех букв (удобно для выравнивания, легко запоминается), это не существительное, и, кроме «объектной модели документа», я не думаю, что к нему прилагается какая-то особая двусмысленность.
pub struct MyStruct {
dom num: i32,
pub msg: String,
}
У кого-нибудь есть мысли по этому поводу?
Один аспект этого, который я видел упомянутым, но не мог найти в резюме (спасибо за это, кстати!), Это то, как ярлык вписывается в существующий синтаксис pub()
.
Если pub
и <something>
(например, crate
) имеют особое значение, это еще больше снижает видимость и, соответственно, знакомство с pub(<something>)
. Какое бы решение мы ни выбрали, я думаю, что оно должно поддерживать или заменять существующее оборудование, а не быть еще одним.
Например, если мы используем crate
или замену:
crate
, чтобы принять ограничения области видимости (например, crate(<something>)
)?pub()
, чтобы pub
имело только одно значение?Принимая во внимание это и мое понимание цели (прояснить общедоступный API из внутреннего API), я решил воссоздать идею @vitiral о pub(extern)
.
pub
сокращением от pub(<something>)
, а не частным случаемpublic
означает, что это может быть в вашем общедоступном API.RE Влияние на инкапсуляцию
Одним из преимуществ существующей системы pub
является инкапсуляция. Простой путь — предоставить API только на один уровень выше. Это упрощает создание общедоступных элементов для частей ящика, но закрытых для всего создания.
Хотя по-прежнему будет pub(super)
, наличие ярлыка для pub(crate)
будет подталкивать людей к тому, чтобы использовать его чаще, побуждая людей не инкапсулировать свои API.
Я подозреваю, что это не проблема из-за культуры маленьких ящиков.
Но, рассматривая это, это дает мне еще одну итерацию моего комментария выше о pub(extern)
pub
должен быть ярлыком для pub(super)
pub(extern)
требуется для вашего общедоступного API.Ранее я поднимал вопрос о переходе людей с других языков. Это лучше согласуется с ними.
public
работает на разных языках.имо это лучший из всех миров. Так что разорвите его и помогите мне понять, почему нет :)
Я до сих пор ненавижу синтаксис pub(foo)
. Гиперболически это выглядит так, как будто он не может решить, является ли это вызовом функции или сочетанием нескольких ключевых слов. Мы не используем let(mut)
или for(in)
, так что с этим?
@parasyte pub<foo>
за победу! В конце концов, разве это не _вид видимости_?
pub<crate>
или pub(crate)
действительно чувствуют себя лучше.
Некоторые мысли от человека, сменившего лагерь:
Сначала я был очень против crate
и думал, что "это портит хороший pub
".
Затем я попробовал его бок о бок в некоторых своих проектах и позволил ему впитаться.
Честно говоря, через несколько дней я больше не мог смотреть на pub(X)
, по сравнению с ним он кажется неуклюжим и трудным для чтения.
Сначала я боялся, что может возникнуть (визуальная) двусмысленность; но со мной случилось обратное: если я сейчас увижу crate
, я знаю, что это, ну, "вещь из ящика". Будь то импорт модулей или объявление видимости. Что именно в подавляющем большинстве случаев очень понятно из контекста (вроде как двусмысленность в английском).
Я вижу, что в некоторых случаях все еще может быть остаточная «более сложная» (визуальная) двусмысленность, но я бы не хотел обменивать ее на то, что теперь кажется огромным количественным выигрышем в удобочитаемости (например: «строки исходного кода, которые требуют меньше визуальной токенизации/усилий по сравнению со строками исходного кода, которые стали более неоднозначными»).
С этой точки зрения crate
- intern
(или любая другая асимметрия) также будет казаться шагом назад.
Сказав это, я не знаю о разборе двусмысленности. Если бы мне нужно было выбрать одну из них, я бы предпочел хорошую историю о том, что « crate
означает ящик», чем хорошую историю о том, что « crate ::foo::bar
просто работает».
Мои два цента в том, что:
crate mod
, crate struct
, crate fn
, ... и считаю его чрезвычайно полезным.crate
, pub(crate)
, ...), если он не слишком длинный, потому что я часто его использую.Если бы это зависело от меня, я бы использовал vis
в качестве ключевого слова и тип видимости в качестве модификатора, например, vis(pub)
, vis(crate)
и т. д., потому что это делает больше мне смысл.
Учитывая, что мы уже застряли с pub
в качестве «спецификатора видимости», мне действительно нравится crate
. Для меня pub(crate)
читается как общедоступный для этого модуля, частный для ящика - я нахожу здесь одновременное использование как общедоступного, так и частного.
Вводить новые ключевые слова и контекстные ключевые слова и т. д., на мой взгляд, не стоит. Обучение тому, что есть две модификации видимости pub
и crate
, и что одно означает общедоступное, а другое означает личное для ящика, для меня имеет смысл, но, возможно, я просто привык к этому. crate
уже за последние две недели.
Тем, кто предполагает, что уже использованное ключевое слово (например, crate
) объединяет значения, я бы сказал, что контекст важнее самого слова. Мозг разбирает все с контекстом (как компилятор разбирает это другой вопрос): это объясняет, почему мы не объединяем семантическое значение for
в for x in y
и impl X for Y
.
В равной степени введение crate
в качестве квалификатора видимости, скорее всего, не вызовет путаницы, поскольку его значение в контексте квалификатора члена или функции очевидно, когда он предоставляется с этим дополнительным контекстом. Например, crate fn my_func();
читается не как «это ящик», а как «это функция, видимая ящиком».
Тем не менее, тот факт, что это существительное, непоследователен. Я был бы за создание нового ключевого слова квалификатора видимости для решения этой проблемы.
На самом деле, если есть что-то, что определенно смутит пользователей, так это синтаксис pub(crate)
, который интуитивно выглядит как вызов функции и не имеет другого синтаксического эквивалента в другом месте языка. Для меня это похоже на уродливый взлом.
Как человек, который выразил обеспокоенность по поводу использования crate
в качестве замены pub(crate)
и после прочтения последнего поста @aturon :
Поддержка crate в качестве модификатора видимости (отслеживается здесь 138. Судя по отзывам, эта функция вряд ли будет стабилизирована для Rust 2018 .
Я просто хочу убедиться, что я ясно понимаю, что лично я полностью за замену pub(crate)
чем- то (как я думаю , что большинство).
В порядке предпочтения, с тем, что, как мне кажется, будет наиболее легко понять, особенно для тех, кто новичок или не знаком с Rust:
intern
(или другое подобное новое ключевое слово)crate
pub(crate)
Если основная команда считает, что intern
или что-то подобное в конечном итоге никогда не будет принято, тогда я откажусь от crate
, так как я все еще думаю, что это большое улучшение по сравнению с pub(crate)
, поскольку причины , которые @Centril и другие сформулировали.
Поэтому я не стал бы этому препятствовать, если бы гораздо более опытная основная команда считала, что это лучший путь вперед. Удобно просто иметь возможность давать обратную связь, выражать идеи для рассмотрения. 👍 Ржавчина!
@ralfbiedert
Сначала я боялся, что может возникнуть (визуальная) двусмысленность; но со мной случилось обратное: если я сейчас увижу ящик, я знаю, что это, ну, "вещь из ящика". Будь то импорт модулей или объявление видимости. Что именно в подавляющем большинстве случаев очень понятно из контекста (вроде как двусмысленность в английском).
@зестерер
Тем, кто предполагает, что уже использованное ключевое слово (например, ящик) объединяет значения, я бы сказал, что контекст важнее самого слова. Мозг анализирует все с учетом контекста (как это анализирует компилятор — другой вопрос): это объясняет, почему мы не объединяем семантическое значение for in для x в y и impl X для Y.
Я не собираюсь призывать вас двоих лично, но послужу примером людей, которые выступают за изменение после его использования.
Хотя я нахожу это странным, больше всего меня беспокоят не рустообразные.
Я был бы рад, если бы мы могли провести исследование юзабилити, чтобы лучше понять, какое влияние оказывают эти опасения.
@epage , полностью согласен, части Rust, ориентированные на пользователя, должны быть протестированы на UX. Однако я думаю, что это то, что происходит прямо сейчас, и мы находимся в процессе обсуждения результатов.
Чтобы добавить к этому, некоторые анекдотические наблюдения от нашей компании:
Я «защитник ржавчины» в нашем отделе, работаю с тремя другими. Все имеют солидный опыт работы с C#, но относительно плохо знакомы с Rust. На днях я перенес наш исследовательский проект на Rust 2018 вместе с " crate
-stuff".
Когда мы проходили код, разговоры шли примерно так:
«Итак, вот некоторые другие изменения, которые я сделал: новая система импорта, модификаторы».
"Что это делает?" (указывая на
use crate::object
иcrate x: object
)
«Импорт из этого ящика». и «Модификатор видимости».
"А, хорошо. Что-нибудь еще изменилось?"
Конец дискуссии.
Конечно, мы еще немного поболтали о новых функциях и о том, следует ли нам использовать определенные шаблоны; но «учебный аспект» этих двух пунктов сводился к нескольким словам и с тех пор (насколько мне известно) не упоминался.
Если я услышу что-нибудь еще в следующий раз, когда мы поговорим, я обновлю этот комментарий.
@ralfbiedert Спасибо, что поделились этим!
@epage , полностью согласен, части Rust, ориентированные на пользователя, должны быть протестированы на UX. Однако я думаю, что это то, что происходит прямо сейчас, и мы находимся в процессе обсуждения результатов.
Хотя я ценю эти анекдоты UX, особенно с точки зрения обучаемости, я не думаю, что могу квалифицировать этот процесс как UX-тестирование. Мой комментарий относится к более формальному процессу, который может помочь получить более глубокое понимание, отсеять предубеждения и т. д.
Вот несколько мыслей от новичка в Rust. Во-первых, я хочу сказать, что что-то, что действительно кажется разумным и приятным с этим языком, — это подход «неизменяемый по умолчанию, закрытый по умолчанию».
Теперь pub
хорош, потому что он прост и ожидаем в современных языках. Я чувствую, что необходимость разучиться этому в контексте Rust и вместо этого повсюду рассыпать другое ключевое слово немного неуклюже. Семантически кажется правильным, что это означает «это кнопка, которая появляется на поле», поле является модулем: видимость «на один уровень выше».
Так что для меня использование crate
или другого ключевого слова такого рода вместо pub
просто вызывает раздражение: если быть общедоступным не по умолчанию, экспорт из ящика должен быть еще более особенным. . То есть API крейта должен быть обозначен особым образом.
Итак, я полностью согласен с @epage , pub
должен остаться прежним, и должна быть введена какая-то pub(extern)
. Ключевые слова в скобках действительно кажутся слишком сложными, поэтому, возможно, они заслуживают специального ключевого слова. Ключевое слово crate
будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика». Или export
на самом деле, я не знаю. Хотя, может быть, все, что я хочу сказать, это велосипедный сарай, и все это сводится к тому, что «ключевые слова неверны». Но pub
настолько распространен, что не кажется чем-то особенным, поэтому он не должен представлять что-то действительно особенное (API, экспортируемый из корзины).
На этих выходных я смотрел выступление на RustConf, в котором в примерах кода использовалось много pub(crate)
, и это действительно заставило меня пожелать старого доброго crate
. Я по-прежнему очень поддерживаю первоначальный план.
@стевеклабник
На этих выходных я смотрел выступление на RustConf, в котором в примерах кода использовалось много pub(crate), и это действительно заставило меня пожелать старый добрый ящик. Я по-прежнему очень поддерживаю первоначальный план.
Контекст этого комментария в основном от RustConf или он учитывает эту ветку и предполагает несогласие с ней? Ранее я предоставил альтернативное решение не для pub(crate)
, а для требований, определяющих любые изменения pub
, и я надеюсь, что оно удовлетворит потребности людей.
Видеть
@superseed
Итак, я полностью согласен с @epage , паб должен остаться прежним и должен быть введен какой-то паб (внешний). Ключевые слова в скобках действительно кажутся слишком сложными, поэтому, возможно, они заслуживают специального ключевого слова. Ключевое слово ящика будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика». Или экспортировать на самом деле, я не знаю. Хотя, может быть, все, что я хочу сказать, это велосипедный сарай, и все это сводится к тому, что «ключевые слова неверны». Но pub настолько распространен, что не кажется чем-то особенным, поэтому он не должен представлять что-то действительно особенное (API, экспортируемый из корзины).
RE "Ключевые слова в скобках действительно кажутся неудобными"
Хотя лично я думал, что они хороши, когда я узнал о них (намного лучше, чем все или ничего friend
), меня больше беспокоит то, что мы не создаем параллельный синтаксис, а либо используем то, что у нас есть, либо находим альтернативное решение.
С другой стороны...
RE Или export
на самом деле,
Я не думаю, что добавление export
противоречит моему предыдущему комментарию, в отличие от crate
. В этом контексте export
можно рассматривать как нечто отличное от видимости. export
означает pub(crate)
. Я подозреваю, что это не будет иметь большой проблемы в обучении.
Я могу пойти любым путем в этом расширении моей первоначальной идеи.
@superseed
pub
[…] видимость "на уровень выше".
Ключевое словоcrate
будет работать в этом смысле, я вижу, что оно означает «это экспортированный член ящика».
Я думаю, что ваше понимание значения этих двух ключевых слов может быть полной противоположностью тому, что предлагается здесь, а именно, что pub
означает общедоступный для всех, а crate
означает доступный из одного и того же ящика.
@epage
В случае с pub(crate)
он предлагает действительно удобную функцию и на самом деле хорошо читается, но на мой взгляд слишком похож на вызов функции. т.е. без синтаксической подсветки я, вероятно, был бы действительно сбит с толку, а подсветка не нужна для понимания семантики языка.
@SimonSapin
В самом деле, и я понимаю, что именно так это и должно пониматься, но crate
— будучи существительным — похоже, объявляет либо ящик (?), либо свойство ящика. Акцент на объявлении, а не на уточнении.
И public
/ pub
— такой вездесущий квалификатор, что (мне!) кажется, что он не должен означать «это экспортировано из ящика». Оно имеет значение «это видно вне того контекста, в котором я нахожусь», как в случае с его использованием для определения видимости члена struct
(и поправьте меня, если я ошибаюсь, но я не не думаю, что в этом случае семантика меняется).
А public/pub — такой вездесущий квалификатор, что (мне!) кажется, что он не должен означать «это экспортировано из ящика». Он имеет значение «это видно вне того контекста, в котором я нахожусь», как в случае с его использованием для определения видимости члена структуры (и поправьте меня, если я ошибаюсь, но я не думаю, что семантика меняется в этом случае).
pub
всегда означало «это экспортировано из ящика» — это не изменение, это уже так. Тот факт, что многие считают иначе, является причиной того, что уровень видимости pub(crate)
вообще повышается.
pub всегда означало "это экспортируется из ящика"
Я думаю, что это понимание также может вызвать некоторую путаницу, потому что это не полная картина. pub
действительно означает «Мне все равно, кто за пределами этого модуля получает доступ к этому элементу/полю/методу». Для экспорта из ящика по-прежнему требуется, чтобы путь к элементу также имел те же самые модификаторы pub
.
Эта деталь довольно обычна во многих языках. Вот почему я не в восторге от unreachable_pub
lint, так как это часть того, что так сильно продвигает эту проблему. Если у меня есть тип, который никогда не экспортируется на верхнем уровне, то изводить меня тем, что я пометил его методы pub
, просто похоже на шум.
@rpjohnst Это действительно то, что всегда означало? Разве это не цепочка «видимый из super
» из верхней части ящика, из-за которой элемент был экспортирован, а не квалификация самого листового элемента как pub
?
Нет, это не вся история, и разъяснение @seanmonstar намекает на остальное. Самым большим исключением является реэкспорт - вы можете pub use
что-то, чьи родительские модули являются частными. Еще более странный пример : вам разрешено использовать элемент pub
в общедоступном интерфейсе, даже если его родительские модули являются частными.
И идя в другом направлении, pub(crate)
и меньшие видимости нельзя обойти таким же образом - вы не можете pub use
то, что еще не pub
, даже если pub use
сам по себе не виден снаружи контейнера.
Таким образом, собственная видимость элемента напрямую связана не с его видимостью для super
, а с его «верхним пределом» видимости в любом месте .
Ооо хорошо, спасибо за разъяснение! Я имел в виду гораздо более наивную модель. Это имеет больше смысла в отношении предыдущих комментариев о «текущем значении паба».
Сегодня мы кратко обсудили на встрече @rust-lang/lang:
crate::foo::bar
struct Foo ( crate :: foo :: Bar )
-- это закрытое поле типа (crate::foo::Bar)
или это поле crate
типа ::foo::Bar
?Ответ: разбираем как путь ( игровая площадка ).
Это кажется... вероятно, мне подходит, потому что я думаю, что пути ::foo::bar
будут становиться все более редкими.
Многие из нас положительно относятся к этому, но остаются сомнения по поводу выбора ключевого слова и того, может ли оно создать путаницу в сочетании с путями crate::foo::bar.
@nikomatsakis , есть записи о встречах или краткое изложение, чтобы мы могли наверстать упущенное? В этой ветке я не видел ни обсуждения хотя бы одной из моих проблем[0], ни большого обсуждения встречных предложений. Может быть, [0] и некоторые другие обсуждались в различных темах, посвященных внутренним вопросам, но это слишком много, чтобы копаться в них.
[0] создание синтаксиса параллельной видимости, отодвигающего pub(...)
в неизвестность с ощущением, что мы должны либо удалить, либо принять pub(...)
@epage
@nikomatsakis , есть записи о встречах или краткое изложение, чтобы мы могли наверстать упущенное?
Нет простите; Мы не обсуждали это очень долго (максимум несколько минут) и не записывали никаких заметок по этому поводу.
@eddyb кратко упомянул my
как более короткий и эргономичный модификатор видимости.
Кажется, я сказал mine
, но my
еще короче, прелесть!
(Для протокола, я полушутил на встрече)
РЕДАКТИРОВАТЬ : если my
является локальным ящиком, можем ли мы заменить pub
на our
? например:
our struct Foo(my FooImpl);
(Для протокола, я полушутил на встрече)
еслиmy
является локальным, можем ли мы заменитьpub
наour
?
Perl: превращая шутки в реальность.
https://perldoc.perl.org/functions/my.html
https://perldoc.perl.org/functions/our.html
my
хорош (и встречался раньше), дело в том, что это не яснее, чем local
, internal
или что-то еще, по отношению к чему (или в свой случай, чей ), в чем и вся проблема.
Неловкая ситуация, в которой мы находимся, заключается в том, что мы хотим иметь три уровня конфиденциальности — «полностью общедоступный», «полностью частный» и «где-то посередине» (т. е. уровень ящика) — и из-за ограничений обратной совместимости мы вы застряли с первым из них обязательно pub
, вторым является неявное значение по умолчанию, и вам нужно придумать что-то новое для третьего. И в английском языке не так много слов, которые точно обозначают «ни полностью глобальное, ни полностью локальное, но где-то посередине».
И ключевое слово crate
— это то, что удовлетворяет этому, потому что прямо в названии указано, какова фактическая область действия — это ящик. Но (прежде чем вы начнете восклицать «Я так и знал !»), цена этого в том, что уже не очевидно, что это модификатор видимости . «Паб» — это сокращение от «общественного», это можно понять интуитивно. Но ни в одном другом языке нет понятия «ящик» (с таким названием); чтобы иметь хоть какую-то надежду понять смысл crate struct
, нужно сначала узнать об этом. 1 Это требует от нас дальнейшего изъятия из «бюджета странности языка», и мнения могут расходиться по поводу того, остается ли баланс положительным.
Между тем, pub(crate)
решает обе проблемы — он говорит вам, что это модификатор видимости, и он сообщает вам, что такое область действия — но взамен он длинный и неудобный.
Так что это в основном форма затруднительного положения.
1 (Кто-то выше описал взаимодействие, которое выглядело так: «Они спросили, что означает crate
, я сказал им, что это модификатор видимости, и на этом все закончилось». Проблемная и, возможно, более распространенная ситуация возникает, когда рядом с вами случайно не сидит рустообразный.)
FWIW, я был бы полностью согласен с our
или my
для местных предметов.
Ключевое слово our
даже состоит из трех букв и прекрасно сочетается с pub
~и с Perl~.
Проблема в том, что они звучат слишком неформально (для носителей английского языка?)?
Как люди относятся к intern
? Это один символ длиннее, чем crate
, но в остальном я думаю, что он будет более интуитивно понятным, чем crate
для людей, плохо знакомых с Rust, и имеет хорошую симметрию с ключевым словом extern
.
IMO our
и my
имеют ту же слабость, что и local
и internal
: они не очень хорошо понимают свою область применения. local
, в частности, довольно сбивает с толку, так как область действия будет радикально отличаться от локальных переменных, где локальная означает закрытую область действия, которая для элемента будет модулем, а не ящиком. Я нахожу internal
немного неконкретным. Внутреннее чему? Модуль? Тип? Ящик? Это может быть очевидно для тех, кто пришел из языков, где он используется, но не обязательно будет для других. our
и my
еще более расплывчаты. Напротив, crate
очень четко указывает на объем.
Что касается pub(extern)
, у меня действительно есть вопрос. Есть ли смысл иметь extern "C" fn foo() {}
без pub
впереди? Потому что если бы это было не так, мы могли бы повторно использовать extern fn foo() {}
и для наших обычных функций Rust, отличных от "C". Я думал, что мы могли бы унифицировать это и не оставлять внешний синтаксис специальным для FFI. Это будет означать, что extern
теперь обесценивается до pub(extern)
, pub
остается таким же, как и сегодня, но принимает необязательную строку ABI, если элемент ее поддерживает, и lint для pub
элементов экспортируется без pub(extern)
или extern
.
extern fn foo() {
println!("Just called a Rust function from Rust!");
}
#[no_mangle]
extern "C" fn foo_from_c() {
println!("Just called a Rust function from C!");
}
Я не видел, чтобы это упоминалось в темах, которые я читал, поэтому извиняюсь, если это обсуждалось раньше!
Есть ли смысл иметь
extern "C" fn foo() {}
без паба впереди?
Да, иногда вы хотите использовать, например, только foo
в качестве указателя функции. И на самом деле синтаксис extern fn foo() {}
не может быть повторно использован для этого в любом случае, потому что extern
без "C"
по умолчанию соответствует C ABI, и это считается идиоматичным, по крайней мере, некоторыми.
Вот предложение, которое появилось давным-давно — может быть, мы можем дать ему еще один шанс сейчас, когда некоторые аспекты новой модульной системы выкристаллизовались?
// Public to the world.
pub struct Foo;
// Private to the crate.
priv struct Foo;
// Basically not visible at all (only inside the module).
struct Foo;
Я считаю, что это имеет смысл, если подумать о:
У некоторых людей была рефлекторная реакция на то, что priv
не является самым ограничительным, но я хочу сделать два замечания по этому поводу:
В Rust модули используются для организации вещей в пространствах имен, а ящики используются для определения интерфейсов. Итак, если крейт — это «единица API», то для модификаторов видимости имеет смысл говорить в первую очередь о крейтах.
Я думаю, что Java допустил ошибку private
, что означает «приватный для класса», а модификатор видимости не означает «видимый внутри пакета». Для меня более разумно, чтобы модификатор не был самым ограничивающим (т. е. по умолчанию).
@stjepang Я бы сказал, что в большинстве других случаев «частное» будет иметь более ограничительный оттенок, чем неизмененное состояние. Спектр частный-стандартный-общедоступный в общем смысле аналогичен защищенному-доступному-рекламируемому.
Частный клуб более эксклюзивен, чем клуб.
Частный акт подразумевает, что были предприняты некоторые усилия, чтобы скрыться от всеобщего обозрения.
Частная мысль должна быть избыточной концепцией, учитывая, что эволюция не смогла наделить нас телепатией, но большинство людей признают, что это означает мысль, предназначенную для того, чтобы ею не делились.
Как неопытный человек, изучающий языки, я бы также предположил, что дополнительное ключевое слово является меньшей когнитивной нагрузкой, чем одно ключевое слово с несколькими контекстно-зависимыми значениями. См. Костелло, Л. и Эббот, Б. «Кто первый», 1938 г.
Я чувствую, что my
и our
будут иметь коннотации, которые нам не нужны, не говоря уже о сложности резервирования их в качестве ключевых слов. Это забавная шутка, но я не думаю, что нам следует идти по этому пути.
Я искренне чувствую, что люди узнают, что означает видимость crate
. Я думаю, что большая проблема связана с кодом, который становится трудно читать или неоднозначно анализировать:
crate struct S(crate crate::Foo);
crate struct S(crate ::Foo);
Я лично не вижу в этом ничего особенного, но здесь они определенно вызывают озабоченность.
В языке Scala есть аналог pub(path)
, который равен private[path]
и действует почти так же. Он читается немного по-другому, говоря: «Этот элемент является частным, его могут просматривать только люди в пределах $path». Но для того, чтобы сделать что-то приватным в Scala, требуется аннотация, так как по умолчанию она общедоступна, чего нельзя сказать о Rust.
Мне приходит в голову, что концепция C++ friend
s также похожа на pub(path)
, как еще одна точка прецедента.
В конечном счете вопросы таковы:
crate
используется как для импорта относительных путей, так и в качестве модификатора видимости,crate
предотвращает унифицированный синтаксис модификатора видимости, такой как pub(...)
,pub(crate)
(слишком длинный, выглядит как вызов функции).После 5 минут действительно глубоких размышлений я придумал следующее... :P
_(на примере @
)_
<strong i="18">@pub</strong> use crate::Foo;
<strong i="19">@crate</strong> struct Bar;
Я лично нахожу это довольно уродливым, и я бы не хотел набирать @crate
или pub(crate)
.
Поскольку уже есть голые pub
и extern
, я думаю, что ключевое слово crate
вполне подходит (неудивительно, если исходить из языков с обычными public
, protected
, private
ключевые слова).
crate struct Foo;
crate fn path() -> PathBuf { ... }
Но, как я уже сказал, это не очень хорошо работает с префиксом импорта crate
, и мне начинает казаться, что мы получили это задом наперед. Я чувствую, что реальная проблема заключается в изменении ясности пути, например, без подсветки синтаксиса:
use crate::utils;
похоже, что crate
не имеет особого значения.
Вдохновленный синтаксисом декларативных макросов, вместо того, чтобы искать какой-то унифицированный синтаксис для модификаторов видимости, я бы предпочел следующее:
use std::io;
use std::path::Path;
use log::info;
use $crate::utils;
crate fn hello() -> io::Result<()> {
utils::rm_rf(Path::new("/"))?;
info!("Goodbye, World!");
}
( Специальные якоря self
, super
и crate
для импорта путей требуют префикса, например, $crate
, из чего совершенно ясно, что они являются специальными и похоже на переменные)
Запутанный пример:
crate struct Foo(crate crate::Bar);
становится:
crate struct Foo(crate $crate::Bar);
Похоже, есть проблема с отслеживанием дубликатов: https://github.com/rust-lang/rust/issues/45388.
Закрытие этого в пользу этого.
Есть ли причина, по которой реализация rustc тестирует эту функцию? Каждый экземпляр crate fn
можно заменить на pub(crate) fn
и перестать полагаться на нестабильную функцию AFAICT.
Я не вижу веских причин, почему мы должны это делать. И Clippy, и rustc постоянно используют нестабильные функции, и они должны это делать, потому что это позволяет нам более тщательно их тестировать как с точки зрения обнаружения ошибок в реализации, так и потому, что мы можем почувствовать, как их использовать.
В этом случае использование crate
в качестве модификатора видимости в Clippy и rustc, на мой взгляд, показывает, что он читается лучше, чем pub(crate)
, и что большинство проблем, упомянутых в этой проблеме отслеживания, не являются -проблемы на практике. Я думаю https://github.com/rust-lang/rust/issues/53120#issuecomment -413466129, https://github.com/rust-lang/rust/issues/53120#issuecomment -414392549 и https:/ /github.com/rust-lang/rust/issues/53120#issuecomment -413498376 также предполагает, что crate
в качестве модификатора видимости хорошо работает и снаружи.
Так как это хорошо работает на практике, так как многие из нас в языковой группе положительно относятся к этому , и поскольку это было принято RFC , я думаю, что мы должны рассмотреть возможность стабилизации crate
в качестве модификатора видимости после рассмотрения того, как мы должны анализировать struct Foo ( crate :: foo :: Bar )
( в настоящее время как путь, и, вероятно, это правильно ).
FWIW, я использую эту функцию в Cargo-n64, и это очень приятно!
Я постоянно использую crate
в rustc, потому что он короткий и не имеет круглых скобок, таких как pub(crate)
.
Хотя мне все равно не нравится, как это читается.
Он также не имеет 3 букв, поэтому форматирование меняется вместе с изменениями pub
<-> crate
.
Мне все еще нравится our
без иронии.
@petrochenkov Я понимаю, что вы написали, так это то, что вы предпочитаете crate
pub(crate)
, но также хотели бы что-то лучше, чем crate
. Это точная оценка?
FWIW, я все еще думаю, что intern
— хороший вариант.
pub(crate)
(хотя один символ длиннее, чем crate
)crate
(который используется для других вещей, таких как пути, например, crate::foo::bar
)extern
internal
). Котлин, С# и т.д.При этом я также согласен с тем, что pub(crate)
следует чем- то заменить.
хорошо, тогда решено - три буквы хорошо, и "стажер" хорошо, так что... int
. ;)
Можем ли мы получить корпию для дела crate ::T
(с пробелом)?
@Centril Некоторые из нас только что обсуждали дальнейшие действия на #rocket. Основываясь на вашем недавнем комментарии, есть ли возможность предложить FCP в ближайшем будущем?
@jhpratt Я собирался написать рецензию и в конечном итоге предложить ее, но я был занят другими вещами. Постараюсь найти время в ближайшее время.
Итак, я просто просматривал выпуски, искал что-то о макросах и нашел это.
Теперь, когда у нас уже давно есть pub(crate)
в стабильной версии, интересно, не следует ли закрыть эту проблему?
Интересно, что это только что всплыло на недавнем собрании команды разработчиков, где обсуждалось это как возможная проблема, которую мы хотели бы возродить.
Говоря лично, я определенно скучаю по возможности писать crate fn
и crate foo: T
в полях и тому подобное. Это небольшое синтаксическое отличие от pub(crate)
, но я считаю, что это делает код более читабельным, особенно в структурах с большим количеством общедоступных полей. Я также считаю, что это способствует разумно полезной, упрощенной «модели конфиденциальности» —
crate
, нужно копировать)pub
)На мой взгляд, между этим ключевым словом и изменениями, предусмотренными в https://github.com/rust-lang/rust/issues/48054 , есть некоторое пересечение, и я бы предпочел, чтобы мы приняли их вместе. Я забыл подробности, но помню, что были ошибки, которые можно было бы получить, пытаясь применить вышеуказанную модель на практике.
Я думаю, что первым шагом к этому было бы то, что кто-то попытался бы написать статью, задокументировав историю и убедившись, что мы выдвинули на первый план все проблемы, которые были подняты.
Одна конкретная проблема, которую я помню, — это синтаксическая двусмысленность
struct Foo(crate ::x)
Сегодня это принято, и crate ::x
анализируется как путь crate::x
, но, вероятно, пользователь имел в виду, что crate
служит модификатором видимости с ::x
в качестве пути. .
Я был бы склонен повторно ввести модификатор crate
и сохранить синтаксический анализ приведенного выше случая таким же, как сегодня. Начиная с Rust 2018, пути ::foo
в значительной степени устарели — они все еще существуют и могут быть полезны в определенных конкретных контекстах, таких как макросы, но в большинстве случаев мы теперь поощряем абсолютные пути, которые выглядят как crate_name::b
, где crate_name
может быть ключевым словом crate
или именем другого ящика. Так что вполне вероятно, что crate::x
(игнорируя пробелы) на самом деле имелось в виду как путь, и, следовательно, текущий синтаксический анализ правильный.
Если мы хотим устранить потенциальную путаницу пользователей, то я думаю, что lint, чувствительный к пробелам, является достаточно хорошей идеей. Другими словами, struct Foo(crate ::x)
выдаст предупреждение, а struct Foo(crate::x)
— нет, хотя оба они приняты и эквивалентны.
Лично я больше предпочитаю унифицированный синтаксис и простой парсер lookahead(1); Кроме того, ящик есть ящик, и существует crates.io , и все эти вещи не имеют ничего общего с видимостью _непосредственно_ — только в контексте pub(_)
.
Но хорошо, что я знаю? Это просто еще одна точка зрения. У вас, ребята, несомненно, больше опыта и более ценное мнение.
@nikomatsakis Любопытно, есть ли у вас какие-либо мысли о intern
для этого варианта использования (или на данный момент резервирование нового ключевого слова выходит за рамки?).
По прошествии пары лет мое мнение осталось прежним: оптимизируйте для удобочитаемости . Я обнаружил, что читаю код гораздо больше, чем пишу его. И так, моё мнение, мне понятнее читать pub(scope)
, что может быть pub
, pub(crate)
, pub(super)
, pub(in proto::h1)
.
Тем не менее, я не думаю, что мы действительно добавляем что-то новое в разговор с этими мнениями, я уверен, что мы сказали все это в предыдущих комментариях. Должно ли решение основываться на чем-то новом? Или, другими словами, как мы решаем, что теперь решение о принятии этого синтаксиса должно быть «да», когда оно было «нет», или отложить пару лет назад?
Я также считаю, что это способствует разумно полезной, упрощенной «модели конфиденциальности» —
- структуры, поля либо локальны для модуля (очень узкое рассуждение)
- или они используются где-то в текущем крейте (
crate
, нужно копировать)- или они общедоступны для всего мира (
pub
)
Я не могу понять преимущества этого упрощения и того, как оно стоит потери в выразительной силе. Что бы это ни стоило, я часто делаю элементы общедоступными для их родительских модулей (чтобы родственные модули могли их использовать), но не для всего ящика. Публично для прародительского модуля в меньшей степени, но все же иногда.
Я чувствую, что отказ pub(super)
будет значительной потерей.
Отдельно я не в восторге от использования существительного crate
в качестве квалификатора, который модифицирует элемент, который может существовать независимо. Для сравнения: pub(lic), unsafe и const(ant) прилагательные. Существительные, уже используемые в качестве ключевых слов в определениях элементов, не являются квалификаторами, а указывают на характер этого элемента: функция, черта, модуль, …
Ящики — это уже концепция, с которой мы имеем дело, но в этом предложении определение предмета, начинающееся с crate
, не определяет новый ящик.
Немного новой информации:
rust-analyzer обеспечивает завершение и помогает добавлять pub(crate)
, что (субъективно) делает ввод текста менее раздражающим при трех нажатиях клавиш.
Я согласен, что здесь добавляется мало новой информации. Я думаю, что хорошим следующим шагом, если мы хотим отстаивать предложение, было бы вернуться назад, обобщить нерешенные проблемы и представить его команде lang, чтобы попытаться принять окончательное решение. Я, конечно, предпочел бы либо принять, либо отклонить это предложение, я устал от того, что оно висит в подвешенном состоянии.
Быстро просмотрев весь этот выпуск, я думаю, что недавний комментарий @nikomatsakis довольно хорошо подводит итог. Помимо нескольких избранных людей, которые все еще поддерживают такие вещи, как intern
, crate
кажется наиболее логичным (и был принят в RFC 2126 ). Единственная действительно нерешенная проблема заключается в том, как анализировать fn foo(crate ::bar)
.
Наиболее логичным местом для начала кажется предупредительный по умолчанию lint, чувствительный к пробелам. crate ::bar
в настоящее время анализируется как путь и должен оставаться таковым как в Rust 2015, так и в 2018. Однако я полагаю, что это будет кандидат на критическое изменение в редакции.
Случай crate ::bar
совершенно не важен на практике и уже ведет себя согласованно с остальной частью языка. Это неизменно было отвлекающим маневром обсуждения, пожалуйста, не заостряйте на этом внимание.
Я, конечно, предпочел бы либо принять, либо отклонить это предложение, я устал от того, что оно висит в подвешенном состоянии.
Думаю, я бы проголосовал за отказ.
Я постоянно использую crate
вместо pub(crate)
в rustc, и, несмотря на то, что он короче, в большинстве случаев он выглядит неуместно, особенно в полях или импорте, и выбирая между crate
и pub(crate)
похоже на выбор из двух зол, при этом не зная, какое из них меньшее.
Да. Что еще более важно, так это то, что @SimonSapin упомянул, что crate bar
действительно не определяет новый ящик, несмотря на то, что он читается как если бы это было так.
@petrochenkov Вы не думаете, что ворс имеет смысл? Лично, если бы я увидел crate ::bar
, не видя этого обсуждения, я бы ожидал, что он будет вести себя как pub(crate) ::bar
. Я думаю, что разрешение пробелов в путях _вообще_ сбивает с толку.
@jhpratt Было бы трудно запретить пробелы между сегментами пути из-за характера работы синтаксических анализаторов с токенами. Также это сломало бы безумное количество инструментов, таких как quote!, syn и многие другие.
Думаю, я бы тоже поддержал закрытие этого. Я видел достаточно путаницы, выраженной в отношении значения этой конструкции, и я не думаю, что выигрыш в краткости стоит потенциальной потери удобочитаемости.
Это может лучше соответствовать «большой» (но закрытой) проблеме отслеживания № 44660, но также напрямую связано с модификаторами видимости и не подходит к другим подзадачам № 44660:
В какой-то момент я помню, как кто-то предположил, что pub(path)
теперь может быть законным, заменив форму pub(in path)
и включив в нее pub(crate)
и pub(super)
. Это кажется хорошим упрощением pub(...)
, хотя и в другом направлении, чем crate
, которое мы также могли бы рассмотреть.
Редактировать: на самом деле не уверен, что это работает... struct S(pub(path) Type)
неоднозначно (для синтаксического анализа в стиле LL) с такими вещами, как struct S(pub (Type,))
.
Так что я думал об этом в течение последних нескольких месяцев. Я думаю, что пришел к "закрытому" положению. Я думаю, что краткое изложение моей позиции выглядит следующим образом:
pub(super)
, в частности, я нахожу очень распространенным на практике, хотя редко требуется более одного уровня (например, pub(crate::foo)
). Например, я часто хочу иметь модули, которые имеют подмодули, и использование видимости ящика для этих деталей не может передать предполагаемый уровень конфиденциальности.pub(crate) fn
, хотя и значительно менее лаконичный, чем просто crate fn
, не так уж и плох. Забавно, что pub(crate)
расширяется до pub(crate::foo)
, что покрывает другой вариант использования, который я иногда получаю (например, «большие» модули в ящике), но это настолько многословно, что я подозреваю, что это будет редко, если вообще когда-либо будет использоваться, и вполне вероятно, что эти большие модули в любом случае лучше разбить на подкрейты...pub(x) fn
, имели подходящую конфиденциальность. Мы изменили эти правила, и я просто чувствую, что больше не сталкиваюсь с этими раздражающими факторами, и если таких раздражающих факторов станет больше, я думаю, мы сможем решить и их.pub
в полях, что означает «такой же общедоступный, как и сама структура», и я думаю, что это прекрасно работает.И, конечно же, тот факт, что если мы не добавим crate fn
сейчас, не означает, что мы не сможем добавить его позже. В частности, я думаю, что модель «трех уровней конфиденциальности» работала бы лучше, если бы у нас был какой-то способ создавать «легкие встроенные ящики» внутри другого ящика. т. е. если бы вместо субмодуля внутри крейта я мог объявить приватный крейт со всеми вытекающими последствиями (в первую очередь, возможно, DAG-подобное отношение к другим вещам). Я не уверен, что легкие, встроенные ящики действительно будут работать, но они могут покрыть и заменить множество вариантов использования, подобных pub(super)
. Если бы я когда-нибудь исследовал это, я бы подумал о повторном открытии обсуждения вокруг crate fn
, так как это может стать значительно более полезным/распространенным.
Короче говоря, я бы высказался за удаление уровня видимости crate
из компилятора и удаление ворот функций.
Я просто хотел проверить, когда эта функция может быть стабилизирована, и я удивлен и разочарован тем, что есть планы по ее удалению. Я использую его изо дня в день с тех пор, как он был добавлен, и меня почти не беспокоят какие-либо из проблем, обсуждавшихся выше. Например, я до сих пор не написал ничего похожего crate ::path
и, вероятно, никогда не напишу, так как никогда не касался синтаксиса ::path
.
Конечно, есть возможности для улучшения. Ключевое слово можно было бы выбрать лучше, pub(super)
по-прежнему неудобно, и неприятно получать предупреждения о мертвом коде повсюду, когда я использую видимость на уровне ящика для вспомогательных методов. Тем не менее, как пользователь, я бы предпочел, чтобы эта функция оставалась (закрытой) до тех пор, пока не будет найдено лучшее решение. Синтаксис pub(crate)
немного раздражает и немного отбивает желание разбивать большие модули на более мелкие и компактные.
думаю, что самые большие эргономические препятствия вокруг «смешанных уровней конфиденциальности» возникли из-за ошибок и ошибок, связанных с тем, что мы пытались гарантировать, что (например) все типы, которые появляются в pub(x)fn, имели подходящую конфиденциальность.
Означает ли это, что мы также не включаем lint «unreachable pub» ( mod private { pub fn f() {} }
)?
Хех, у меня были другие мысли, когда я читал различные коды rustc и видел, как crate
используется, и я думаю, что все эти случаи были pub(crate)
… вероятно, стоило бы сделать переход экспериментально, просто чтобы посмотреть, как разница заставляет меня чувствовать. Я помню, как мне было грустно из-за мела, когда мы перенесли его из ночного в конюшню, хотя я думаю, что теперь, когда я к нему привык, это меня не так сильно беспокоило.
@matklad Надеюсь, нет, я думаю, что ворс тоже очень важен. Честно говоря, я не совсем понимаю, почему я не сталкивался с такими ошибками и неприятностями, как раньше. Возможно, в последнее время я просто недостаточно пишу код на Rust! Я точно помню, что раньше у меня были эти надоедливые циклы, когда казалось, что я не могу удовлетворить компилятор, кроме как делать больше вещей pub
, чем мне хотелось.
Как насчет сохранения pub(crate)
и добавления псевдонима pubc
? Это читается очень похоже, не нарушает текущий код и устраняет необходимость вводить круглые скобки (что делает его немного быстрее).
Это также позволит pubs
для видимости в родительском элементе.
Короче говоря, я бы высказался за удаление уровня видимости
crate
из компилятора и за удаление гейта функций.
Я считаю, что pub(crate)
немного раздражает и шумит, когда я читаю код. Вместо этого было бы неплохо иметь модификатор видимости crate
.
И, конечно же, тот факт, что если мы не добавим
crate fn
сейчас, не означает, что мы не сможем добавить его позже. В частности, я думаю, что модель «трех уровней конфиденциальности» работала бы лучше, если бы у нас был какой-то способ создавать «легкие встроенные ящики» внутри другого ящика. т. е. если бы вместо подмодуля внутри крейта я мог бы объявить приватный _crate_ со всеми вытекающими последствиями (в первую очередь, возможно, DAG-подобное отношение к другим вещам). Я не уверен, что легкие, встроенные ящики действительно будут работать, но они могут покрыть и заменить множество вариантов использования, подобныхpub(super)
. Если бы я когда-нибудь исследовал это, я бы подумал о повторном открытии обсужденияcrate fn
, так как это может стать значительно более полезным/распространенным.
Мне определенно понравились бы эти "легкие" ящики, о которых вы говорите! Это было бы намного приятнее, чем сразу переходить к рабочим пространствам, которые довольно тяжелые.
Самый полезный комментарий
Я лично не против написать
pub(crate)
, намерение кажется очень явным.Пример, приведенный @johnthagen , действительно больно видеть (используя
crate
):crate mod color;
особенно кажется запутанным, вам определенно нужно немного подумать о том, что там происходит.