Udostępnij za pośrednictwem


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

  1. 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).
  2. Czy powinniśmy zaakceptować ogólny wzorzec po .. w slice_pattern? (odpowiedź [LDM 2021-05-26]: Tak, każdy wzorzec jest dopuszczalny po wycinku.)
  3. Zgodnie z tą definicją wzorzec [..] testuje expr.Length >= 0. Czy należy pominąć taki test, zakładając, że Length zawsze nie jest ujemna? (odpowiedź [LDM 2021-05-26]: [..] nie będzie przeprowadzać kontroli długości)