Wzorce listy
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są ujęte w odpowiednich notatkach z posiedzenia dotyczącego projektowania języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Problem z liderem: https://github.com/dotnet/csharplang/issues/3435
Streszczenie
Pozwala dopasować tablicę lub listę do sekwencji wzorców, np. array is [1, 2, 3]
będzie pasować do tablicy całkowitej o długości trzech z elementami 1, 2, 3.
Szczegółowy projekt
Składnia wzorca jest modyfikowana w następujący sposób:
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
;
Istnieją dwa nowe wzorce:
- list_pattern służy do dopasowywania elementów.
- slice_pattern jest dozwolona tylko raz i tylko bezpośrednio w list_pattern_clause i odrzuca zero lub więcej elementów.
Zgodność wzorca
list_pattern jest zgodny z dowolnym typem, który jest zliczalny oraz indeksowalny — posiada dostępny indeksator, który przyjmuje Index
jako argument, lub inny dostępny indeksator z jednym parametrem int
. Jeśli oba indeksatory są obecne, preferowane jest poprzednie.
slice_pattern z podwzorcą jest zgodny z dowolnym typem, który jest zliczalny, a także fragmentowalny — ma dostępny indeksator, który przyjmuje Range
jako argument lub w inny sposób dostępną metodę Slice
z dwoma parametrami int
. Jeśli oba są obecne, preferowane jest poprzednie.
slice_pattern bez podwzorcy jest zgodny z dowolnym typem zgodnym z list_pattern.
Ten zestaw reguł pochodzi ze wzorca indeksatora zakresu .
Sprawdzanie subsumpcji
Sprawdzanie subsumpcji działa podobnie jak wzorce pozycyjne z ITuple
— odpowiednie podwzory są dopasowywane przez położenie oraz dodatkowy węzeł do testowania długości.
Na przykład następujący kod generuje błąd, ponieważ oba wzorce dają ten sam daG:
case [_, .., 1]: // expr.Length is >= 2 && expr[^1] is 1
case [.., _, 1]: // expr.Length is >= 2 && expr[^1] is 1
W odróżnieniu od
case [_, 1, ..]: // expr.Length is >= 2 && expr[1] is 1
case [.., 1, _]: // expr.Length is >= 2 && expr[^2] is 1
Kolejność dopasowywania podwzorców w czasie wykonywania jest nieokreślona, a w przypadku nieudanego dopasowania, może ono nie próbować dopasować wszystkich podwzorców.
Biorąc pod uwagę określoną długość, możliwe, że dwa podwzorcy odnoszą się do tego samego elementu, w takim przypadku test dla tej wartości zostaje wstawiony do drzewa decyzyjnego DAG.
- Na przykład
[_, >0, ..] or [.., <=0, _]
staje sięlength >= 2 && ([1] > 0 || length == 3 || [^2] <= 0)
, gdy wartość długości 3 oznacza drugi test. - Z drugiej strony
[_, >0, ..] and [.., <=0, _]
staje sięlength >= 2 && [1] > 0 && length != 3 && [^2] <= 0
, gdy wartość długości 3 nie zezwala na drugi test.
W związku z tym błąd jest generowany dla czegoś takiego jak case [.., p]: case [p]:
, ponieważ w czasie wykonywania dopasowujemy ten sam element w drugim przykładzie.
Jeśli podwzorce wycinka pasują do listy lub wartości długości, podwzorce są traktowane tak, jakby były bezpośrednim podwzorcami zawierającej listy. Na przykład [..[1, 2, 3]]
subsumuje wzorzec o postaci [1, 2, 3]
.
Dla używanych członków przyjmuje się następujące założenia:
- Przyjmuje się, że właściwość sprawiająca, iż typ jest zliczalny, zawsze zwraca wartość nieujemną wtedy i tylko wtedy, gdy typ ten jest indeksowalny . Na przykład wzorzec
{ Length: -1 }
nigdy nie może być zgodny z tablicą. - Element członkowski, który umożliwia, aby typ można było pociąć, jest uznawany za dobrze zachowujący się, to znaczy, że zwracana wartość nigdy nie jest zerem i że jest to prawidłowa podlista listy zawierającej.
Zachowanie operacji dopasowywania wzorca jest niezdefiniowane, jeśli którekolwiek z powyższych założeń nie zostaje spełnione.
Obniżenie
Wzorzec formularza expr is [1, 2, 3]
jest odpowiednikiem następującego kodu:
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 działa jak prawidłowe odrzucenie, tzn. dla takiego wzorca nie będą generowane żadne testy, lecz będzie to wpływać tylko na inne węzły, jak długość i indeksator. Na przykład wzorzec w formacie expr is [1, .. var s, 3]
jest odpowiednikiem następującego kodu (jeśli jest zgodny poprzez explicitne wsparcie Index
i 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
Typ danych wejściowych dla slice_pattern jest typem zwrotnym bazowej metody this[Range]
lub Slice
z dwoma wyjątkami: w przypadku string
i tablic zostaną użyte odpowiednio string.Substring
i RuntimeHelpers.GetSubArray
.
Nierozwiązane pytania
- Czy powinniśmy obsługiwać tablice wielowymiarowe? (odpowiedź [LDM 2021-05-26]: Nieobsługiwane. Jeśli chcemy utworzyć ogólną wersję skoncentrowaną na tablicy MD, chcemy ponownie przejrzeć wszystkie obszary, których obecnie brakuje, a nie tylko wzorce listy).
- Czy powinniśmy zaakceptować ogólny wzorzec po
..
w slice_pattern? (odpowiedź [LDM 2021-05-26]: Tak, każdy wzorzec jest dopuszczalny po wycinku.) - Zgodnie z tą definicją wzorzec
[..]
testujeexpr.Length >= 0
. Czy należy pominąć taki test, zakładając, żeLength
zawsze nie jest ujemna? (odpowiedź [LDM 2021-05-26]:[..]
nie będzie przeprowadzać kontroli długości)
C# feature specifications