Vzory seznamů
Poznámka
Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.
Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách schůzky o návrhu jazyka (LDM) .
Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .
Problém šampiona: https://github.com/dotnet/csharplang/issues/3435
Shrnutí
Umožňuje spárovat matici nebo seznam se sekvencí vzorů, například array is [1, 2, 3]
bude odpovídat celočíselné matici s délkou 1, 2, 3 jako jejími prvky.
Podrobný návrh
Syntaxe vzoru se upraví následujícím způsobem:
list_pattern_clause
: '[' (pattern (',' pattern)* ','?)? ']'
;
list_pattern
: list_pattern_clause simple_designation?
;
slice_pattern
: '..' pattern?
;
primary_pattern
: list_pattern
| slice_pattern
| // all of the pattern forms previously defined
;
Existují dva nové vzory:
- Vzor seznamu se používá k porovnání prvků.
- slice_pattern je povoleno pouze jednou a pouze přímo v rámci list_pattern_clause a vynechává nula nebo více prvků.
Kompatibilita vzorů
list_pattern je kompatibilní s libovolným typem, který je počitatelný, stejně jako indexovatelný — má přístupný indexer, který přebírá Index
jako argument, nebo jinak přístupný indexer s jediným parametrem int
. Pokud jsou oba indexery přítomny, je upřednostňovaný první indexer.
slice_pattern s podpatternem je kompatibilní s libovolným typem, který je počítatelný a krájetelný – má přístupný indexer, který přijímá Range
jako argument, nebo jinak přístupnou metodu Slice
se dvěma parametry int
. Pokud jsou oba přítomny, je upřednostňovaný první.
slice_pattern bez dílčího vzoru je kompatibilní s každým typem kompatibilním s list_pattern.
Tato sada pravidel je odvozena ze vzoru indexeru rozsahu .
Kontrola subsumpce
Kontrola subsumpce funguje stejně jako poziční vzory s ITuple
– odpovídající podvzory se shodují podle pozice a dalším uzlem pro ověření délky.
Například následující kód vytvoří chybu, protože oba vzory poskytují stejný DAG:
case [_, .., 1]: // expr.Length is >= 2 && expr[^1] is 1
case [.., _, 1]: // expr.Length is >= 2 && expr[^1] is 1
Na rozdíl od:
case [_, 1, ..]: // expr.Length is >= 2 && expr[1] is 1
case [.., 1, _]: // expr.Length is >= 2 && expr[^2] is 1
Pořadí, ve kterém se podvzorů shodují během zpracování, není specifikováno, a pokud dojde k neúspěšné shodě, nemusí se pokusit sladit všechny podvzorů.
Pokud vezmeme v úvahu specifickou délku, je možné, že dvě dílčí vzory odkazují na stejný prvek; v takovém případě se do rozhodovacího DAG vloží test této hodnoty.
- Například
[_, >0, ..] or [.., <=0, _]
se stanelength >= 2 && ([1] > 0 || length == 3 || [^2] <= 0)
, kde hodnota délky 3 znamená druhý test. - Naopak
[_, >0, ..] and [.., <=0, _]
se stanelength >= 2 && [1] > 0 && length != 3 && [^2] <= 0
, kde hodnota délky 3 zakáže druhý test.
Výsledkem je, že se pro něco jako case [.., p]: case [p]:
vytvoří chyba, protože za běhu porovnáváme stejný prvek ve druhém případě.
Pokud podvzorec řezu odpovídá seznamu nebo hodnotě délky, jsou podvzorce považovány za přímé podvzorce seznamu, který je obsahuje. Například [..[1, 2, 3]]
zahrnuje vzor ve formě [1, 2, 3]
.
Předpokládají se následující skutečnosti týkající se používaných členů:
- Vlastnost, která dělá typ spočitatelným, je předpokládána, že vždy vrátí nezápornou hodnotu, a to jedině pokud je typ indexovatelný. Například vzor
{ Length: -1 }
nemůže odpovídat poli. - Člen, který dělá typ řezatelným, je považován za dobře se chovajícího, to znamená, že návratová hodnota není nikdy null a jedná se o správný podřez obsahujícího seznamu.
Chování operace porovnávání vzorů není definováno, pokud se některé z výše uvedených předpokladů neudrží.
Snížení
Vzor formuláře expr is [1, 2, 3]
odpovídá následujícímu kódu:
expr.Length is 3
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Index(1, fromEnd: false)] is 2
&& expr[new Index(2, fromEnd: false)] is 3
slice_pattern funguje jako běžné zahození, tj. pro takový vzor se nevygenerují žádné testy, ale ovlivní pouze jiné uzly, konkrétně délku a indexátor. Vzor formuláře expr is [1, .. var s, 3]
je například ekvivalentní následujícímu kódu (pokud je kompatibilní prostřednictvím explicitní podpory Index
a Range
):
expr.Length is >= 2
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))] is var s
&& expr[new Index(1, fromEnd: true)] is 3
Vstupní typ pro slice_pattern je návratovým typem podkladové this[Range]
nebo Slice
metody se dvěma výjimkami: Pro string
a pole se použijí string.Substring
a RuntimeHelpers.GetSubArray
.
Nevyřešené otázky
- Měli bychom podporovat vícerozměrná pole? (odpověď [LDM 2021-05-26]: Nepodporuje se. Pokud chceme vytvořit obecnou verzi zaměřenou na pole MD, chtěli bychom se znovu vrátit ke všem oblastem, které aktuálně chybí, nejen vzory seznamů.)
- Měli bychom přijmout obecný vzor , který následuje po
..
v části s posloupností ? (odpověď [LDM 2021-05-26]: Ano, jakýkoli vzor je povolený po řezu.) - Podle této definice vzor
[..]
testujeexpr.Length >= 0
. Měli bychom takový test vynechat, za předpokladu, žeLength
je vždy nezáporná? (odpověď [LDM 2021-05-26]:[..]
nevyvolá kontrolu délky)
C# feature specifications