Pull to refresh

Comments 14

Весьма и весьма красиво! Я сам любитель навертеть чего-нибудь удобного и необычного на синтаксических фишках языка.
Одно предложение: добавьте, пожалуйста, экстеншн метод аля ToFunc, чтобы можно было объявлять матчеры через var, а то много пользователей, среди которых я, пишут сначала new Matcher...., а потом жмут introduce variable в решарпере. В этом случае можно написать .ToFunc и тип станет функцией:

  public static class MatcherEx
  {
    public static Func<T1, T2> ToFunc<T1, T2>(this Matcher<T1, T2> matcher)
    {
      return matcher;
    }
  }
  ...
  var matcher = new Matcher<string, int>
  {
    {s => true, s => s.Length}
  }.ToFunc();

  var i = matcher("asd");

Отличная идея! Честно говоря, долго думал, как же сделать возможность не указывать явно полную сигнатуру Func. Обновил пакет
При всем моем уважении, это не pattern matching ни разу. Все что угодно, но не _сопоставление с образцом_.
Вас смущает отсутствие готовых дискриминаторов для коллекций?
Нет конечно :-)
В первую очередь, меня «смущает» отсутствие _образца_ как такового. Предикат не является образцом, и не может таковым быть. По той простой причине, что предикат не способен определить контекст, связывающий… кхм… скажем так… «правую» и «левую» части «выражения» сопоставления.
Вы правы, но единственный способ так сделать, который мне удалось придумать — объединять предикат и функцию в объект «дискриминатор», что выглядит уже не так красиво

У меня была изначально идея сделать что-то вроде
s => string.IsNullOrEmpty(s) => 0

Но C# не позволяет писать такие выражения.
Да дело-то не в этом.

Каким именно образом будет задаваться _образец_ дело конечно важное, но не настолько.

Проблема как раз в том, что результат сопоставления — это — грубо говоря — не true/false. Результат сопоставления — это контекст. Сам процесс сопоставления — это, по большому счету, процесс построения контекста. Удалось построить — сопоставление удалось. Не удалось — результатом будет контекст, определяющий исключительную ситуацию в том или ином виде.

Если «на пальцах» — то в вашем случае, вычисление правого выражения пары, должно происходить в контексте, полученном в результате вычисления левого выражения пары. Т.е. левое выражение должно быть не предикатом, а функцией возвращающей, например, Expression.
Вроде в C# есть замыкания. Объединение легко делается как замыкание, получающее параметрами две функции, и вызывающая одну из них с параметром нужного типа.
Добрый день, скажите а почему вам не подошли похожие решения вроде May(http://twistedoakstudios.com/blog/Post1130_when-null-is-not-enough-an-option-type-for-c) или Scalesque(http://noelkennedy.github.io/scalesque/)?
Здравствуйте. Scalesque не использует деревьев выражений, что порождает оверхед на вызовы функций при сопоставлении. May я не находил ранее, но судя по коду он работает схожим со Scalesque образом
Понятно, т.е. вы бы не рекомендовали ваше решение тем для кого быстродействие критично? Вопрос без подвоха.
Моё решение по сути генерирует код, эквивалентный цепочным if'ам. Единственное, что стоит учитывать — время компиляции Expression, но она происходит лишь однажды — при первом сопоставлении либо при приведении к Func.
По крайней мере, при использовании ExprMatcher в продакшене деградации производительности по сравнению с цепочным if'ом замечено не было
Sign up to leave a comment.

Articles