порядок операторов в выражении запроса F#

Имеет ли значение порядок операторов выражения запроса? Не знаю, но иногда (в некоторых случаях) это так, а иногда нет (или, может быть, это так, но неявно обрабатывает некоторые конкретные случаи).

Является ли обязательным, чтобы оператор select шел последним? почти в каждой комбинации он ругается, если вы не пишете его как последний оператор, но в случае take n этот оператор может идти после select

Меня просто интересует как действует процесс исполнения?

Это подводит меня к другому вопросу. Если он выполняет итерацию по коллекции Iterable и, таким образом, на первой итерации выбирает какое-то одно (первое) значение, как order работает с этим одним (первым) значением? было бы ясно, если бы сначала он возвращал последовательность, а затем выполнял порядок в этой последовательности... но похоже, что он выполняет sortBy на каждой итерации (?). Меня интересует, какова конструкция исполняемого алгоритма.

Вот мой пример выражения запроса.

let sq = query {
   for p in datasource do
   where p.age>20
   sortBy p.age
   select p
}

Объяснения были бы очень признательны.

Спасибо


person Giorgi Tsiklauri    schedule 08.12.2016    source источник
comment
Вы уверены, что этот вопрос правильно помечен? Я не признаю ничего из этого стандартным F#. Кроме того, конкретный пример кода, как правило, очень помогает.   -  person Anton Schwaighofer    schedule 08.12.2016
comment
Не так много объяснений, но, возможно, github.com/fsharp/fsharp и, возможно, более конкретно: github.com/fsharp/fsharp/blob/master/src/ fsharp/FSharp.Core/ и github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/ И если вы новичок в CE: docs.microsoft.com/en-us/dotnet/articles/fsharp/. Я предполагаю, что вы прочитали мелкий шрифт в docs .microsoft.com/en-us/dotnet/articles/fsharp/   -  person Helge Rene Urholm    schedule 09.12.2016
comment
@AntonSchwaighofer, мне все это кажется стандартным: docs.microsoft.com/en-us/dotnet/articles/fsharp/   -  person Phillip Scott Givens    schedule 09.12.2016
comment
@PhillipScottGivens: первая версия вопроса не содержала никакого фактического кода, и вывод кода из естественного языка обычно немного неоднозначен.   -  person Anton Schwaighofer    schedule 12.12.2016


Ответы (2)


Нам не нужно гадать, мы можем узнать.

let sample = Seq.init 10 (fun i -> i * 10) |> Seq.map (fun i -> { age =  i }) 
let sq = query {
   for p in sample do
   where (p.age > 20)       
   sortBy p.age
   select p
}

sq |> Seq.toList |> ignore

Сгенерированный IL (очищенный) выглядит так

IL_004e: newobj instance void Program/sq@16::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder)
IL_0053: callvirt instance [...] For<class Program/Person,      
IL_005d: callvirt instance [...] Where<class Program/Person,    
IL_0067: callvirt instance [...] SortBy<class Program/Person,   
IL_0071: callvirt instance [...] Select<class Program/Person,   

Предположим, мы меняем порядок sortBy

let sq = query {
   for p in sample do
   sortBy p.age
   where (p.age > 20)       
   select p
}

Новый ИЖ будет:

IL_006c: callvirt instance [...] For<class Program/Person,      
IL_0076: callvirt instance [...] SortBy<class Program/Person,   
IL_0080: callvirt instance [...] Where<class Program/Person,    
IL_008a: callvirt instance [...] Select<class Program/Person,   

Вы можете ясно видеть, что он следует точному порядку, в котором вы определяете запрос. Это не имеет значения для понимания T-SQL, потому что запрос будет переведен посетителем Expression, но для объектных запросов выражения запроса в значительной степени являются просто синтаксическим сахаром. для тебя.

person Asti    schedule 09.12.2016

Способ №2:

Вы можете расширить модуль выражения запроса, включив в него оператор побочных эффектов. Это просто порт метода DoAction Interactive Extensions.

module QueryExtensions =

    type QueryBuilderEx() =
        inherit Linq.QueryBuilder()

        [<CustomOperation("doAction", MaintainsVariableSpace = true)>]
        member __.Do(source : Linq.QuerySource<'T,System.Collections.IEnumerable>, action) =            
            new Linq.QuerySource<'T,System.Collections.IEnumerable>(source.Source |> Seq.map (fun v -> action(v); v))


let query = QueryExtensions.QueryBuilderEx()

Теперь вы можете отлаживать порядок так

let sq = query {
       for p in sample do
       sortBy p.age       
       where (p.age > 20)       
       doAction (printfn "Next -> %A")
       select p
    }

Если вы переместите его выше where, вы увидите, что он отражает эти записи перед фильтрацией.

person Asti    schedule 09.12.2016
comment
Чтобы уточнить, @Astri расширяет query вычислительный выражение. Спасибо @astri за этот приятный маленький трюк. - person Phillip Scott Givens; 09.12.2016
comment
@PhillipScottGivens, добро пожаловать! В System.Interactive есть много хороших операторов, которых я бы хотел использовать в FSharp Seq. - person Asti; 09.12.2016