Есть ли цель или польза в запрете повторного связывания переменных без сигилов?

В попытке лучше понять переменные без сигил и как они отличаются от $ я обнаружил, что в отличие от переменных $ переменные с сигилами, переменные без сигилов не могут быть восстановлены после инициализации:

my $a = 42;
my $b := $a;
$b := 42;       # No exception generated

my \c := $a;
c := 42;        # OUTPUT: «Cannot use bind operator with this left-hand side␤»

Это по замыслу? Если да, то есть ли цель или выгода запретить повторное связывание переменных без сигилов, когда $ переменные с сигилом не запрещены?

2 ответа

Решение

Да, это, конечно, дизайн, и - как и большинство вещей в дизайне Perl (6) - это так по нескольким причинам.

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

  • Синтаксическая неоднозначность (вы можете вызывать переменную как угодно, даже если есть ключевое слово с таким именем)
  • Удобочитаемость (данные в программе выдаются благодаря символу)
  • Определение семантики присваивания (в Perl 6 присвоение означает "копировать в", таким образом my @a = @b означает итерацию @b и положить каждую вещь в это в @aТаким образом, любые будущие назначения @b не повлияет @a)
  • Ограничение того, что можно связать там (только Positional вещи для @, например)
  • В случае с $контролируя то, что будет считаться одним предметом
  • В случае @ на параметр подписи, вызывая входящий Seq быть кэшированным

Таким образом, каждый символ содержит набор полезных поведений по умолчанию для данных, которые следует рассматривать как отдельный элемент ($), что-то, чтобы индексировать в позиционно (@) что-то для индексации с помощью ключа (%) и то, что можно назвать (&). Каждый из них, как в контексте назначения, низкоуровневого связывания, так и связывания подписи, несет обычно желательную семантику для данных такого типа.

Это хорошо, пока кто-то не захочет написать код, который будет полиморфным для всех этих поведений, или не будет придерживаться какого-либо поведения сигилов. Более ранние итерации дизайна языка Perl 6 имели что-то вроде sub foo($x is parcel) { }, где is parcel вещь фактически означала "не навязывать никакой семантики сигил-й", за исключением того, что это было довольно запутанным, потому что вещь имела $ сигил, но был исключен из семантики. Было понято, что если бы поведение сигил не применялось, то было бы лучше, если бы оно выглядело по-другому (принцип дизайна "разные вещи должны выглядеть по-разному", который также неоднократно проявляется в Perl). Самый очевидный способ выглядеть по-другому - это не иметь сигилу.

Однако по синтаксическим соображениям в сигнатуре нужно было что-то использовать для устранения неоднозначности имени, вводимого из типа (поскольку сигнатура (Foo) соответствовать по типу Foo но игнорируйте значение, которое уже было поддержано и полезно, и мы не хотели потерять это). \ был выбран, чтобы играть эту роль, получая sub foo(\x) { }, который затем позволил использование x внутри подпрограммы.

Насколько я помню, разрешив эту форму в случае my пришел чуть позже, хотя я не совсем уверен в этом. Одна из важных вещей о том, что символ без знака не фиксирует поведение, состоит в том, что он также не фиксирует поведение присваивания, таким образом, = он немного более поздний (где это возможно, компилятор рассматривает сигил и выдает совсем другой код для $/& а также @/% задания). Конечно, если символ связан со значением, тогда никакое присвоение невозможно.

Это оставляет вопрос обязательного поведения. Было решено сделать символ без сигилы формой синтаксиса "статического одиночного назначения", как объяснено в одном из других ответов. Для этого были разные причины, в том числе:

  • Помощь в сохранении свойства читабельности "данных выделяется" для сигил, по крайней мере, следя за тем, чтобы все, что должно быть (немедленно) изменяемым, все еще содержало сигилу
  • Также улучшается читаемость программы благодаря наличию формы, которая позволяет читателю узнать, что символ никогда не будет возвращен к новому значению, так что можно эффективно считать его постоянным в пределах области видимости. Это согласуется с тем, что легко объявить реальным constantбез сигил
  • Осторожно поощряйте более функциональный стиль (возможно, заставляя тех, кто решит, что они ненавидят сигилы, возвращать остальным нам код, который, по крайней мере, более читабелен другим способом, чем предлагают сигилы:-))

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

Переменные без сигилов имеют семантику одиночного статического присваивания.

Преимущества возможности оптимизации

Цитирование из раздела "Преимущества" вышеупомянутой связанной страницы SSA:

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

y := 1
y := 2
x := y

Люди могут видеть, что первое назначение не является необходимым, и что ценность y используется в третьей строке происходит от второго назначения y, Чтобы определить это, программа должна выполнить анализ достигнутого определения. Но если программа в форме SSA, оба из них являются немедленными:

y1 := 1
y2 := 2
x1 := y2

Алгоритмы оптимизации компилятора, которые либо включены, либо сильно улучшены с помощью SSA, включают [длинный список доступных оптимизаций].

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

Преимущества человеческого мышления

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

(По этой причине я склонен считать, что привязка переменной без сигил к контейнеру, как я показал в своем комментарии к вашему вопросу, особенно привязка к Scalar контейнер, это сомнительная практика.)

Другие вопросы по тегам