Сбросить строки оператора LINQ "from"

Я использую библиотеку Sprache, которая позволяет создавать парсеры с использованием LINQ. Однако иногда мне нужно что-то анализировать, а затем отбрасывать результат. Например:

from key in Identifier
from __ws1 in OptionalWhitespace
from __setter in PropertySetter
from __ws2 in OptionalWhitespace
from value in PropertyValue
select ...

Мне не нужна ни одна из трех переменных с префиксом __так что кажется ненужным загрязнять пространство имен ими.

Можно ли как-нибудь выполнить запрос LINQ и отбросить эти три результата?

2 ответа

Решение

Не имея глубоких знаний Sprache, я очень упростил пример, чтобы понять проблемную область.

Возьмите этот пример нескольких операторов from (используя LinqPad), где нас интересует только одно из значений from. Таким образом, в этом произвольном примере мы хотим знать все комбинации людей и торта, но заинтересованы только в названиях торта.

var people = new List<string> {
    "Billy", "Jimmy"
};

var cake = new List<string> {
    "Carrot Cake", "Chocolate Cake"
};

(from p in people
from c in cake
select new
{
    c
}).Dump();

Множественные операторы from можно рассматривать как вложенные циклы foreach, которые в итоге оказываются перекрестным соединением (как обсуждено здесь LINQ Join с несколькими предложениями From)

Итак, давайте предположим, что это намерение авторов Sprache, если мы попытаемся переписать это в свободном синтаксисе (как обсуждено здесь: https://codeblog.jonskeet.uk/2011/01/28/reimplementing-linq-to-objects-part-41-how-query-expressions-work/) /) SelectMany().

В итоге получается что-то вроде:

people.SelectMany(p => cake, (p, c) => new { c }).Dump();

Который вы до сих пор в конечном итоге с человеком "paramater".

Поэтому я бы посоветовал придерживаться намерения Спрейша, что нет способа не иметь __ операторов. Если, возможно, вы сами не построите дерево выражений, но я не могу представить, что это будет продуктивно.

В этом конкретном случае вы можете использовать Then отказаться от всех несущественных частей одновременно:

var parser =
    from key in Identifier
    from _ in OptionalWhitespace
        .Then(_ => PropertySetter)
        .Then(_ => OptionalWhitespace)
    from value in PropertyValue
    select new
    {
        key,
        value
    };

Но в общем случае это не поможет, если не относящиеся к делу части не будут сразу следовать друг за другом.

Sprache реализует методы запросов LINQ для монадического связывания функций синтаксического анализатора, например комбинатор синтаксического анализатора. (LINQ можно использовать для гораздо более интересных вещей, чем запрос EF DbSets.) К сожалению, discard не поддерживается для переменных диапазона запроса LINQ (пока), поэтому ваши переменные диапазона '_' будут конфликтовать в области видимости. Я обычно называю переменные диапазона, которые мне не нужны, например '_N' (где N в [1..]), когда у меня в запросе более одной, и надеюсь не забыть использовать правильные сбросы, когда они будут поддерживаться.

Другие вопросы по тегам