Я хотел бы предложить добавить сопоставление с образцом в GDScript, и я хотел бы его реализовать.
На данный момент в GDScript нет оператора switch
- вам нужно связать несколько операторов if.
_ (Весь синтаксис здесь всего лишь первый набросок, предложения приветствуются) _
Сопоставление с образцом - это проверка структуры и содержимого значения для выполнения перехода.
Таким образом, для простых значений (например, чисел, строк) он действует как статус переключения.
var num = 42
match num:
0: print("Zero")
23: print("Half way there")
42: print("The answer")
Отличие от оператора switch
том, что эти случаи могут быть вложенными. Например, вы можете сопоставить содержимое массива.
var array = [13, "37", ["test", "array"]]
match array:
[13, "37", ["test", "array"]]: print("Wow, a perfect match!")
[13, 37, ..]: print("l33t man") # .. matches the rest of the array
[]: print("empty array")
Сопоставление по словарю будет работать так же, за исключением того, что сопоставление по ключам будет невозможно.
Словари будут сопоставлены по ключу и значению.
Вместо простого ветвления в зависимости от равенства значений можно было бы привязать новые переменные.
Когда встречается первый шаблон, соответствующий значению, будет выполнена соответствующая ветвь. Если шаблон не соответствует, пробуется следующий. Поэтому * более общие шаблоны следует определять под более конкретными.
Чтобы привязать новую переменную, вы просто напишите новый идентификатор вместо значения.
var array = [13, "37", ["test", "array"]]
match array:
[13, "37", [var a, var b]]: print(a, ", ", b) # a = "test", b = "array"
var n: print("Unknown array structure: " + str(n))
При сопоставлении словарей только значение может быть привязано. например, {"test": var a}
Простое совпадение по новому идентификатору равносильно случаю default
в switch
-выражениях.
_Дай мне знать, что ты думаешь _: blush:
Получите: +1: от меня :) сделайте haskell: P
Мне это нравится, потому что синтаксис в основном эквивалентен переключателю (пропадание полосы, но кому это все равно нужно), но при необходимости может быть более мощным
Я предполагаю, что вы имеете в виду это принять блок операторов:
var num = 42
match num:
0:
do_the_zero_routine()
print("Zero")
23:
print("Half way there")
42:
print("The answer")
make_it_sparkle()
@vnen Да, конечно!
Я не понимаю, насколько полезен такой синтаксис по сравнению со стоимостью его реализации в GDScript. Мне почти никогда не приходилось делать это ни в одной игре, которую я делал. И когда мне нужно было такое сопоставление, это было просто реализовано с некоторыми условиями.
Просто подбрасываю сюда идею.
В Haskell можно добавить защиту к каждому шаблону, например:
case [1, 3, 3, 7] of
[1, a, b, 7] | a * 10 + b < 42 -> "Ok, passed the test"
| otherwise -> "That is unacceptable!" -- otherwise = True
_ -> "I won't inspect you! >=D"
Возможный синтаксис GDScript может быть примерно таким:
match [1, 3, 3, 7]:
[1, var a, var b, 7]
if a * 10 + b < 42: print("Ok, passed the test")
[1, var a, var b, 7]: print("That is unacceptable!")
_: print("I won't inspect you! >=D")
Мне кажется, что if
более питонский, но он добавляет намного больше шума в код.
Также при выборе маршрута if
я не знаю, следует ли реализовать случай otherwise
. Падение тоже работает, как в примере.
@Zylann Я думаю, что это намного понятнее и легче для чтения, чем несколько if
s. Но конечно, это не _необходимо_, но я думаю, что это было бы отличным дополнением к языку, потому что им действительно приятно пользоваться. Но это, конечно, субъективно.
Стоимость производительности не должна быть такой высокой. Я бы преобразовал эти вложенные шаблоны в несколько простых совпадений шаблонов. Если шаблон не соответствует при первой проверке, проверяется следующий случай, поэтому он будет не намного медленнее, чем if
s.
Что ж, я согласен, что следует избегать штрафов за производительность. Я не уверен, будет ли этот синтаксис более дорогостоящим, чем обычная цепочка if
. Это во многом зависит от реализации.
@vnen относительно реализации, я хочу реализовать ее, как описано в этой книге. (Реализация функциональных языков программирования Саймоном Пейтоном Джонсом)
edit: Я не буду реализовывать это таким образом, потому что GDscript - это язык с динамической типизацией, и выполнение подобной компиляции потребует излишне сложных преобразований и проверок во время выполнения.
Пример перевода из
match array:
[1, 3, var a]: print(a)
_: print("No match")
к
if typeof(array) == TYPE_ARRAY:
if array[0] == 1:
if array[1] == 3:
var a = array[2]
if array.size() == 3:
print(a)
else:
var n = array
print("No match")
Таким образом, сложность несовпадающих выражений не должна оказывать существенного влияния на скорость выполнения по сравнению с написанными вручную if
s.
@karroffel ну, меня это сбивает с толку. Не то чтобы его чтение сбивало с толку, но со всеми текущими функциями GDScript он выглядит как инопланетянин, и я не вижу, где это можно часто использовать. Я никогда не работал с функциональными языками вроде Haskell, кстати: s
@Zylann его можно использовать везде, где можно использовать переключатель. Просто прочтите это как оператор switch: wink:
Я понимаю отсутствие «необходимости» в этом, но тогда я могу возразить, что циклы for
не нужны, потому что есть if
-выражения и рекурсия: смеется:
Как я уже сказал, вы можете делать все в GDScript без средства сопоставления с образцом, но как только вы привыкнете к сопоставлению с образцом, оно станет действительно полезным и мощным.
var inventory = ["sword", "shield", "magic key"]
match inventory:
["sword", "shield", "magic key"]:
print("You came as a pure warrior, Welcome!")
can_open_door = true
break;
["sword", "shield", ..]:
can_kill_monster = true
can_broke_door = true
can_evade_monster = true
break;
["sword", .. ]:
can_broke_door = true
break;
["shield", .. ]:
can_evade_monster = true
break;
@karroffel Будет ли это возможно?
Будет ли реализован формат отрицательного шаблона, чтобы ".." не совпадал с "волшебным ключом" для последних трех случаев? Или операторы «если» внутри этих блоков case лучше подходят для этой ситуации.
Должно ли это сопоставление с образцом быть таким же полнофункциональным, как регулярные выражения? : D (не спрашиваю, некоторые из них просто похожи)
Для меня наличие отрицательного шаблона (а не регулярного выражения) будет вариантом использования, потому что это сделает кодирование сценария простым и читаемым. Но если результат будет меньше этого, я бы предпочел обычные операторы «switch» и «if», если только нет побочного преимущества, такого как увеличение производительности или меньшее количество LoC.
Примечание: может быть и больше этого тоже не сработает. :)
Массивы @hubbyist зависят от порядка, поэтому ваш пример не будет работать таким образом. ..
существует только для того, чтобы игнорировать остальную часть массива и сопоставлять ее (потому что это зависит от порядка, и вас не волнует остальное, например, только первые несколько элементов). Словари не имеют определенного порядка, возможно, я мог бы добавить специальный синтаксис, чтобы просто сопоставить ключи, чтобы использовать его как обычный набор.
О, и вам не понадобится break
потому что нет провалов
@Zylann Нет, он будет сравнивать только переменные равенства и связывания, и все это может быть вложено.
Вчера реализовал парсер. Я добавил "набор синтаксиса" для словарей, чтобы проверить наличие ключа.
var inventory = {"sword": 20, "shield": 100, "magic key": 2}
match inventory:
{"sword", "shield", "magic key"}:
print("You came as a pure warrior, Welcome!")
can_open_door = true
{"sword", "shield", ..}:
can_kill_monster = true
can_broke_door = true
can_evade_monster = true
{"sword", .. }:
can_broke_door = true
{"shield", .. }:
can_evade_monster = true
Итак, в этом примере мне не важны значения, я просто хочу проверить, присутствует ли свойство.
Также можно использовать простые константные выражения в качестве шаблона, например:
var size = 1024 * 1024 * 1024 # GiB
match size:
1024:
print("KiB")
1024 * 1024:
print("MiB")
1024 * 1024 * 1024:
print("GiB")
_:
print("something different")
Сегодня я преобразовываю это в if
s и var
s, и тогда большая часть тяжелой работы будет сделана.
Я бы хотел, чтобы это было реализовано. Я спрашиваю о переключателях каждые 3-6 месяцев :)
@karroffel По поводу охранников, pattern if cond
звучит неплохо: smile:
(Я говорю о таких случаях, как
var arr = [1,2,3]
var first_required_value = 1
match arr:
[x, ..] if x == first_required_value:
foo(bar)
a:
printerr("Bad luck")
)
Будет ли разрешено и else/elif
?
Сначала: сопоставление констант уже завершено, так что в основном переключатель (он наконец-то здесь !!), теперь мне нужно работать над сопоставлением массивов и словарей ...
Я пока не знаю, как эффективно реализовать провал. Чтобы максимизировать эффективность, я хочу отсортировать шаблоны, поэтому общий «провал» может быть проблематичным. (если я не сортирую, мне, возможно, придется проверять содержимое массива несколько раз)
@Zylann Мне все еще нужно подумать о том, как реализовать охрану. else
должно быть разрешено, если охранники разрешены ИМО, но также должен быть провал, если нет else
и другие охранники терпят неудачу, так что сейчас это немного проблематично.
Что-то вроде стиля try-catch может быть лучше, чем провал IMO.
var inventory = {"sword": 20, "shield": 100, "magic key": 2}
match inventory:
{"sword", "shield", "magic key"}:
print("You came as a pure warrior, Welcome!")
can_open_door = true
...
...
...
{"shield", .. }:
can_evade_monster = true
nomatch:
print("You can't do anything here!")
Он будет более читабельным и при необходимости может быть объединен с другим оператором сопоставления или вызовом функции.
Я думаю, что при отсутствии совпадений else
было бы более читаемым (хотя не уверен, должно ли оно быть внутри или вне блока).
Что о;
match x:
...
...
otherwise:
...
синтаксис?
Использование else
похоже на перегрузку ключевого слова.
Обычно при сопоставлении с образцом используются:
_
= соответствует чему угодно, если совпадения нет ("шаблон подстановки"). Не привязывает идентификатор.
Это согласовано на всех языках, которые я знаю: Haskell, Scala, Elm, Racket, F #, OCaml, Rust. Я не думаю, что есть исключение.
Итак, идиоматический способ сделать это, чтобы оставаться в гармонии с другими языками, которые имеют сопоставление с образцом, должно заключаться в использовании _
.
Между прочим, все эти языки обычно (не всегда, Scala не поддерживает iirc) реализуют какой-то шаблон Nothing
, когда нет значения (что отличается от провала).
Итак, после обсуждения охранников в IRC (спасибо @ akien-mga) я думаю, что мы пришли к хорошему компромиссу.
Вместо добавления охранников можно использовать continue
для проверки других шаблонов. Таким образом, охранники будут просто if/else
s в коде ветвления, а отказ / падение будет выполняться через continue
.
Это упрощает анализатор, а шаблоны немного легче читать.
Я думаю, что _
должен быть шаблоном подстановки по умолчанию.
Я проведу сопоставление по порядку, что может быть более неэффективным, но упрощает многие преобразования.
Честно говоря, я бы просто реализовал стандартный синтаксис переключателя просто потому, что
пользователи много просят об этом, и не пойдут дальше этого
Пт, 7 октября 2016 г., в 9:12, Karroffel [email protected] написал:
Итак, после обсуждения охранников в IRC (спасибо @ akien-mga
https://github.com/akien-mga) Думаю, мы нашли хороший компромисс.Вместо добавления охранников можно использовать continue для проверки
другие шаблоны. Таким образом, охранники будут простыми, если / elses в коде ветвления
и неудача / провал будет происходить через continue.
Это упрощает анализатор, а шаблоны немного легче читать.Я думаю, что _ должен быть шаблоном подстановки по умолчанию.
Я проведу сопоставление по порядку, что может быть более неэффективным, но это
упрощает многие преобразования.-
Вы получаете это, потому что подписаны на эту ветку.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/godotengine/godot/issues/6593#issuecomment -252236803,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AF-Z24qABylU7GPi4UNXJ1myXyKsGcIdks5qxjcRgaJpZM4KFJl9
.
@reduz Понятно , но зачем отказываться от функций, которые не нужно использовать, они необязательны. Здесь есть все функции переключения, а сопоставление с образцом стало гораздо более распространенным явлением в языках программирования в целом.
Если к языку добавляется новая конструкция, я не понимаю, почему ее следует делать менее мощной, чем она могла бы быть.
И, как я уже много раз говорил, этот синтаксис не высечен на камне, его можно изменить на синтаксис переключателя, не отбрасывая дополнительные функции.
наивный вопрос: нет
match size:
1024:
print("KiB")
1024 * 1024:
print("MiB")
1024 * 1024 * 1024:
print("GiB")
a:
print("something different")
такой же как :
switch size:
case 1024 :
print("KiB")
# implicit break
case 1024 * 1024 :
print("MiB")
# implicit break
case 1024 * 1024 * 1024 :
print("GiB")
# implicit break
case a :
print("something different")
# implicit break
???
Так разве это не просто вопрос добавления / замены ключевых слов и сохранения более мощного сопоставления с образцом?
@SuperUserNameMan Это то же самое. (но case a
будет default
)
Вот что я говорю, можно было бы использовать синтаксис переключателя, но сохранить все деструктивные функции сопоставления с образцом.
при использовании этого для выполнения базового switch/case
(без использования более мощных функций сопоставления с образцом) добавляет ли он дополнительных затрат по сравнению с эквивалентом if/elif/else
:
if size == 1024 : print("KiB");
elif size == 1024 * 1024 : print("MiB");
elif size == 1024 * 1024 * 1024 : print("GiB");
else : print("something different");
?
генерирует ли он больше кодов операций?
код, стоящий за ним, такой же быстрый?
@SuperUserNameMan базовая проверка типов необходима для обнаружения недопустимых проверок равенства. В остальном код будет таким же, как вы его написали.
Я поддерживаю это. Идея убрать функциональность из того, что суггестивший может реализовать сам, не имеет смысла. Люди могут использовать его как переключатель, но также могут использовать сопоставление с образцом. Я не понимаю, почему это нужно замалчивать.
@karroffel : тогда я лично не вижу причин (я if/elif/else
.
Таким образом, это будет просто вопрос замены / добавления традиционных switch/case/default
ключевых слов, чтобы он выглядел более «знакомым» и более «дружелюбным».
(кстати, возможно, ключевое слово case
можно сделать необязательным, а switch
можно сделать псевдонимом match
... таким образом, все будут счастливы)
(кстати, может быть, ключевое слово case можно сделать необязательным, а переключатель можно сделать псевдонимом соответствия ... таким образом, все будут счастливы)
Нет, попытка сделать всех счастливыми таким образом ведет к раздуванию, ужасному синтаксису и UX. Найдите лучший синтаксис и обеспечьте его соблюдение.
В "обычных" операторах switch должен быть break
чтобы избежать провала, который не является идиоматическим стилем сопоставления _pattern_. Таким образом, смешивание этих синтаксисов потребует учета того, какой синтаксис использовался, и код должен быть сгенерирован по-другому. Я хотел бы иметь единый синтаксис
Я хотел бы предложить использовать синтаксис соответствия. Не было бы обязательного break
и даже в операторах switch провал очень редок.
Все, что меняется, это:
switch
на match
case
и break
continue
Вот и все. Функциональность есть, указание на оператор соответствия в документации должно быть достаточно, так как каждый новичок в любом случае должен изучить GDscript.
Использование break
в switch
es в первую очередь для меня не интуитивно
Лично мне не нравится писать ключевое слово break
в операторах switch. В основном это лишняя строка кода, которая почти не нужна. Если начинается другой случай, это явный признак того, что предыдущий завершился. Падение просто работает для объединения нескольких вариантов в одну функцию, и только это делает разрыв полным. Но это можно сделать, объединив пустые случаи в один случай с ключевым словом or
например, используя метод switch(true):
или используя ключевое слово continue
как предлагает @karroffel.
continue
- это программный способ сделать это. Я не вижу причин не реализовывать в шаблонах что-то вроде 1, 2, 3
или даже 1 .. 3
. Да, это увеличило бы сложность, но также и обязательный перерыв.
Можно ли воспроизвести использование этого переключателя с сопоставлением с образцом? (псевдокод)
switch(val):
case 0:
return false
case 1:
case 2:
case 3:
print("Stuff")
break
case 4:
print("42")
break
default:
print("Default")
@Zylann
match val:
0: return false
var x:
if x >= 1 && x <= 3:
print("Stuff")
else:
continue
4: print("42")
_: print("Default")
а может я добавлю что-то вроде этого
match val:
0: return false
1 .. 3: print("Stuff")
# different version
# 1, 2, 3: print("Stuff")
4: print("42")
_: print("Default")
Что, если _
- существующая переменная? В конце концов, это правильное имя :)
@Zylann _
- это своего рода узор, а не привязка имени. Если бы это было имя, оно бы затеняло другую переменную, но поскольку это всего лишь шаблон, ничего особенного не происходит, и старый _
все еще можно использовать
Что произойдет, если вы поставите _:
не в качестве последнего совпадения? Должен ли он выдать ошибку?
@Zylann Ну, он соответствует всему, поэтому все после этого не будет выполнено, за исключением случаев, когда вы помещаете continue
внутри ветки.
Таким образом, он не должен выдавать ошибку, потому что вы можете продолжить выполнение с continue
Что касается конструкции 1..3
, я предпочитаю, безусловно, x,y,z
one.
Обоснование:
match 1..3
неоднозначно. Соответствую ли я полному шаблону или одному из членов ранжирования по жанрам? Что, если я действительно хочу сопоставить массив, который выглядит как [1,2,3]
?match http_response:
200: "data loaded successfully"
403,404,500: "an error occurred"
или
match tile_at(x,y):
TILE_WATER:
drown()
TILE_WALL,TILE_BARREL,TILE_CHAR,TILE_SPIKE:
stop()
continue
TILE_SPIKE:
life = life -2
Не связано, но что касается реализаций в стране грез, мне нравится, что в некоторых языках совпадение - это выражение, поэтому вы можете сделать что-то вроде:
var acceleration = match input:
UP:
vector(1,0)
DOWN:
vector(-1,0)
Не защищая этого, поскольку синтаксис типа пробелов GD делает его громоздким, просто подумал, что это интересная вещь :)
Для людей, выступающих за switch
против match
. Я, честно говоря, не вижу для этого веской рациональной причины
Это будет немного долго, не потому, что я так сильно забочусь об этом (я, вероятно, почти никогда сам не буду использовать switch
из match
), а потому, что мне нужен конво быть более конструктивным, а не теряться в путанице.
Вот аргументы против match
, из того, что я могу собрать:
Начнем с аргумента 1:
match делает все, что делает switch, за исключением провала по умолчанию.
Однако по умолчанию падение составляет:
break
после каждого case
. Я уверен, что он существует, но никогда не видел его )continue
).TL; DR : match
делает все, что switch
делает хорошо, избегая ловушек switch
, _and_ допускает более глубокую семантику, если программист желает их использовать (не в случае с switch
, который менее гибкий, чем обычный ifs
)
Аргумент в пользу знакомства также ошибочен, поскольку GD - это собственный язык, и не должно возникнуть проблем с изучением одного нового слова.
В качестве альтернативы аргумент знакомства должен быть расширен до: пробелов в качестве синтаксиса, elif
, без фигурных скобок, один файл = один класс, ... Все это может быть или не быть знакомым, в зависимости от того, на каком языке вы использовал раньше. Например, для меня ничего из вышеперечисленного не подходит, а вот match
подходит.
В Python даже нет switch
(и не зря), поэтому даже обращение к синтаксической близости GD с Python не является допустимым аргументом.
Но, если предположить, что переключатель «знаком» (что, опять же, действительно зависит от того, с какого языка вы пришли, но допустим, что это так, ради аргумента), для программиста, ищущего документ и заменяющего
switch val:
case a:
do_something()
break;
case b:
do_something_else()
break;
с участием:
match val:
a:
do_something()
b:
do_something_else()
... банально.
Практически нет никакой кривой обучения. Для того, кто читает код, так же легко понять, что происходит, даже если вы никогда раньше не видели match
. Кстати, именно так я узнал о конструкции match
: читал код и натыкался на него. Мне не потребовалось больше доли секунды, чтобы понять, что это всего лишь чистильщик switch
без break
s и case
s. Конечно, для понимания того, насколько мощно это было необходимо для чтения документации, но для понимания этого достаточно, чтобы использовать его везде, где можно было бы использовать switch
, требуется от 1 до 10 секунд обучения.
Новичку легче научиться, и ему не нужно разбираться в том, что такое падение, или не забывать добавлять break
после каждого утверждения.
TL, DR : аргумент о знакомстве не работает; Во-первых, это субъективно. Во-вторых, даже если предположить, что это правда, для программиста изучение немного другого синтаксиса является нормой для курса, а для непрограммистов совпадение с меньшей вероятностью будет ошибочным, но его немного легче изучить (тот же синтаксис минус одна конструкция ).
Таким образом, это предложение по улучшению языка:
elif
вместо else if
)Я думаю, что можно использовать константы в качестве шаблона (для сопоставления с такими вещами, как TYPE_FLOAT
или около того). Проблема в том, что во время синтаксического анализа (где я выполняю преобразования) невозможно определить, называет ли StringName константу или нет.
Таким образом, чтобы различать константы и привязки, необходимо использовать var name
для привязки и просто SOME_CONSTANT
для констант. (Я обновлю примеры в своем первоначальном комментарии)
Для сопоставления шаблонов разных типов необходимо добавить простую проверку типов, чтобы избежать ошибок во время выполнения. Чтобы не усложнять задачу, я просто хочу делать такие вещи (на самом деле сейчас я делаю это так):
match 4:
"hello": print("It's a string that says \"hello\"")
4: print("It's 4")
# compiles to something like this
var match_value = 4 # actually it's "#match_value"
# this name can only be created by the compiler
# but this messes up syntax highlighting ;)
if typeof(match_value) == typeof("hello") && match_value == "hello":
print("It's a string that says \"hello\"")
# goto end
if typeof(match_value) == typeof(4) && match_value == 4:
print("It's 4")
# goto end
# end:
Если вы попытаетесь сопоставить шаблоны, которые имеют побочные эффекты, шаблон будет выполняться _twice_ (из-за проверки типов), поэтому было бы нехорошо использовать шаблоны с побочными эффектами. Я мог бы обойти это, но это потребовало бы учета временных переменных, которые только усложнили бы всю трансформацию.
Поэтому я бы сказал, что следует избегать паттернов с побочными эффектами, но не запрещать их. Что вы думаете?
Что такое паттерн с побочными эффектами? Вызов функции в шаблоне?
match val:
get_some_int(val): some_effect()
get_some_other_int(val): some_other_effect()
...Что?
И да, я думаю, что использование var
для объявления переменных в шаблоне менее запутанно и более уместно.
цитата из: @Xananax
Я думаю, что использование var для объявления переменных в шаблоне менее запутанно и более уместно.
: +1:
@Xananax нет, что-то вроде этого:
var counter = 0
func side_effect_pls(x):
counter += x
if counter > 1:
return x
return counter
...
match 3:
side_effect_pls(3): print("<- that's baaad")
Да, я это имел в виду.
Я думаю, что это может быть полезно (возможность вызывать функции в шаблоне), но если из-за этого реализация становится слишком сложной, то это того не стоит. Его всегда можно реализовать позже, если люди об этом попросят.
«Не кодируйте для среднего случая, не кодируйте для лучшего или худшего случая, кодируйте для наиболее часто используемого случая и останавливайтесь на этом» - какой-то чувак, я не помню, кто.
Должен следовать принципу @reduz : «Добавляйте минимум, необходимый для работы. Добавляйте больше, только если многие люди об этом просят».
Как вы собираетесь подсчитывать людей, которые его просят? Сколько это много?
Пальцами. Если не влезет в одну руку, наверное, много.
Есть ли причина, по которой вам нужно использовать подчеркивание для подстановочного знака провала ? Это исключает возможность использования его в качестве переменной
@ClikCode
Провалиться? Прохождение выполняется с помощью continue
. Вы имеете в виду шаблоны с подстановочными знаками.
Цитата Xananax:
Это согласовано на всех языках, которые я знаю: Haskell, Scala, Elm, Racket, F #, OCaml, Rust. Я не думаю, что есть исключение.
Таким образом, идиоматический способ сделать это, чтобы оставаться в гармонии с другими языками, которые имеют сопоставление с образцом, должно заключаться в использовании _.
@karroffel Все эти языки функциональны или сильно функциональны. А как насчет императивных языков?
@ bojidar-bg в большинстве императивных языков нет сопоставления с образцом, поэтому привести пример невозможно.
В C # 7 будет некоторая форма сопоставления с образцом, но это просто дополнение к базовому switch
, поэтому здесь это бесполезно.
В императивных языках нет сопоставления с образцом, потому что его корни в алгебраических типах данных, которые до сих пор не приняты в императивных языках. Во многих современных языках есть сопоставление с образцом, поскольку они также имеют алгебраические типы данных. Так что это в основном исторический момент.
~матч бла:1: print («Я - кто-то»)еще:print ("Я никто")~
Как бы это сделал питон, если бы они когда-либо сделали это
@ClikCode а что насчет
match x:
[1, _, _, 7]: print("kek")
[1, else, else, 7]
не особо приятен для глаз.
как насчет использования '?' или "*" вместо символа "_"? Они используются в качестве подстановочных знаков для регулярных выражений, чтобы не сильно отличаться от сопоставления с образцом. Это оставит допустимые символы имени переменной вне синтаксиса сопоставления с образцом.
Что случилось с «переменными должны иметь описательные имена»? Есть ли веская причина, по которой кто-то захочет вызвать переменную _
если он не хочет, чтобы она была забыта ?
func (_,x) => x+1
Неявное значение функции выше заключается в том, что первый аргумент пропускается (даже не читая его тело). Независимо от сопоставления с образцом, я сомневаюсь, что вы можете обосновать свое желание вызвать переменную _
, если , опять же, вы не хотите ее использовать.
«Подчеркивание» библиотеки javascript называется _
именно потому, что никто никогда не будет использовать его в качестве имени переменной и поэтому является относительно «безопасным» глобальным.
За 20 лет работы с кодом с открытым исходным кодом в маленьких и больших компаниях я ни разу не видел, чтобы кто-то использовал _
в качестве имени переменной, если только они действительно не хотели, чтобы об этом забыли. Я не говорю, что мой анекдотический опыт является доказательством чего-либо, но это все же показатель.
Вот и «почему». Я понимаю, что это не убедительный аргумент, кто-то все еще может захотеть назвать переменную _
, но, тем не менее, рассмотрение наиболее распространенного случая важно.
Во-вторых; в некоторых языках (не знаю , если реализация Годо делает это), то _
делает решимость к тому , что был принят; Это полезная переменная, тогда как синтаксически невозможно использовать ?
или *
для того же эффекта.
например:
match val:
0: print("it's a zero")
4: print("it's a four")
[_]: prints("it's an array containing",_)
_: prints("it's a ",_)
Опять же, я не знаю, есть ли это у реализации Карроффеля (не во всех реализациях сопоставления есть), но независимо от этого; это полезное удобство и потенциально может быть добавлено позже. Это причина, по которой было выбрано подчеркивание, а не зарезервированное ключевое слово или недопустимый символ имени переменной.
Наконец; Использование и совместимость с общим синтаксисом превосходит это незначительное удобство. Для этого кодера со своим особым стилем, который любит использовать _
, мы бы:
@Xananax, спасибо, что _
- лучший выбор.
В настоящее время я просто игнорирую значение, но это будет лишь небольшое дополнение, которое сделает _
полезной переменной. Если об этом попросят, я добавлю это.
😄 если да, пожалуйста, сделайте _
полезной переменной
(проблема с тем, чтобы сделать его пригодным для использования идентификатором, состоит в том, что _
может встречаться в шаблоне несколько раз. Какое значение следует использовать? до обсуждения ...)
«Добавьте минимум, необходимый для работы. Добавляйте больше, только если многие люди об этом просят»
я цитирую внен цитирую редук
Похоже, мне придется вмешаться в это дело. Я действительно не ожидаю, что мое предложение найдет какую-либо поддержку, но все же есть некоторые вещи, о которых следует упомянуть.
@karroffel
Позвольте мне рассказать об удобстве использования Python по этой теме:
match foo:
[_, _]: print("what ever")
можно так же легко заменить на
match foo:
[*, *]: print("what ever")
Проблема с этим будет в том, что его сложнее набирать, по крайней мере, на моей американской клавиатуре, но есть множество других символов, которыми можно пожертвовать ради переменной, которую можно выбросить.
match foo:
[*, *]: print("what ever")
относительно использования _
в качестве значения, возвращаемого для подстановочного знака. Я считаю, что вы это уже реализовали.
match bar:
var n: print("Unknown array structure: " + str(n))
так же легко может быть:
match bar:
var _: print("Unknown array structure: " + str(_))
Единственная проблема в том, что это выглядит не так красиво. Но это по-прежнему помогает с удобочитаемостью, поскольку вы соблюдаете правила для всех допустимых имен переменных.
@Xananax
Думаю, вы как бы доказали мою точку зрения. библиотека underscore
для javascript использует _
потому что она так редко используется для чего-либо еще. Но сейчас его используют, не так ли?
Я не думаю, что использование других языков - лучший способ вести этот разговор.
Относительно полезности подчеркивания как переменной, которая разрешает все, что было передано.
для этого шаблона [1, _, _, 2]:print(_)
какой из них будет напечатан? Не то чтобы это было ясно. Попробуйте вместо этого [1, *, var _, 2]: print(_)
и мы все знаем, какой из них будет напечатан, не так ли.
Моя проблема не в том, что используется подчеркивание, моя проблема в использовании допустимого имени переменной. Так что либо измените допустимые переменные, либо измените реализацию.
Вы говорите новичку: «Переменная - это имя для значения, она может использовать любую букву, цифру или символ подчеркивания, и она должна начинаться либо с буквы, либо с подчеркивания. Вы можете использовать это где угодно, кроме здесь. , здесь и здесь ".
С уважением, всем, кто нашел время послушать.
Самый полезный комментарий
Для людей, выступающих за
switch
противmatch
. Я, честно говоря, не вижу для этого веской рациональной причиныЭто будет немного долго, не потому, что я так сильно забочусь об этом (я, вероятно, почти никогда сам не буду использовать
switch
изmatch
), а потому, что мне нужен конво быть более конструктивным, а не теряться в путанице.Вот аргументы против
match
, из того, что я могу собрать:Начнем с аргумента 1:
match делает все, что делает switch, за исключением провала по умолчанию.
Однако по умолчанию падение составляет:
break
после каждогоcase
. Я уверен, что он существует, но никогда не видел его )continue
).TL; DR :
match
делает все, чтоswitch
делает хорошо, избегая ловушекswitch
, _and_ допускает более глубокую семантику, если программист желает их использовать (не в случае сswitch
, который менее гибкий, чем обычныйifs
)Аргумент в пользу знакомства также ошибочен, поскольку GD - это собственный язык, и не должно возникнуть проблем с изучением одного нового слова.
В качестве альтернативы аргумент знакомства должен быть расширен до: пробелов в качестве синтаксиса,
elif
, без фигурных скобок, один файл = один класс, ... Все это может быть или не быть знакомым, в зависимости от того, на каком языке вы использовал раньше. Например, для меня ничего из вышеперечисленного не подходит, а вотmatch
подходит.В Python даже нет
switch
(и не зря), поэтому даже обращение к синтаксической близости GD с Python не является допустимым аргументом.Но, если предположить, что переключатель «знаком» (что, опять же, действительно зависит от того, с какого языка вы пришли, но допустим, что это так, ради аргумента), для программиста, ищущего документ и заменяющего
с участием:
... банально.
Практически нет никакой кривой обучения. Для того, кто читает код, так же легко понять, что происходит, даже если вы никогда раньше не видели
match
. Кстати, именно так я узнал о конструкцииmatch
: читал код и натыкался на него. Мне не потребовалось больше доли секунды, чтобы понять, что это всего лишь чистильщикswitch
безbreak
s иcase
s. Конечно, для понимания того, насколько мощно это было необходимо для чтения документации, но для понимания этого достаточно, чтобы использовать его везде, где можно было бы использоватьswitch
, требуется от 1 до 10 секунд обучения.Новичку легче научиться, и ему не нужно разбираться в том, что такое падение, или не забывать добавлять
break
после каждого утверждения.TL, DR : аргумент о знакомстве не работает; Во-первых, это субъективно. Во-вторых, даже если предположить, что это правда, для программиста изучение немного другого синтаксиса является нормой для курса, а для непрограммистов совпадение с меньшей вероятностью будет ошибочным, но его немного легче изучить (тот же синтаксис минус одна конструкция ).
Таким образом, это предложение по улучшению языка:
elif
вместоelse if
)