How to return a query from an anonymous function and pass it to a forward pipe

StackOverflow https://stackoverflow.com/questions/23349225

  •  11-07-2023
  •  | 
  •  

Question

I have a query that is then forward piped to an anonymous function. I would like this function to utilize the query and then forward pipe it to the next function. Not sure if this possible as I am having trouble accomplishing this.

so far I have this:

// find file for deletion
let findFileToDelete id = 

    // query
    query{
        for row in db.Uploads do
        where (row.Id = id)
        select row
        exactlyOneOrDefault
    } 
    |> (fun q -> File.Delete(q.FilePath)) 

But I would like to continue on with something like this:

// find file for deletion
let findFileToDelete id = 

    // query
    query{
        for row in db.Uploads do
        where (row.Id = id)
        select row
        exactlyOneOrDefault
    } 
    |> (fun q -> File.Delete(q.FilePath)) q // forward pipe the query
    |> deleteRowFrom db.Uploads q

    // update the database
    saveToDb()
Was it helpful?

Solution

As Mark pointed out, pipelining is generally used for a series of transformations. Your code performs a series of actions. I recommend writing it like this:

// find file for deletion
let findFileToDelete id = 

    let row = 
        query {
            for row in db.Uploads do
            where (row.Id = id)
            exactlyOneOrDefault
        } 

    File.Delete row.FilePath
    deleteRowFrom db.Uploads row

    // update the database
    saveToDb()

OTHER TIPS

F# has significant whitespace, and the most normal way of separating multiple statements is by separating them with a newline, so you should be able to do something like this:

let findFileToDelete id = 

    // query
    query{
        for row in db.Uploads do
        where (row.Id = id)
        select row
        exactlyOneOrDefault
    } 
    |> (fun q ->
        File.Delete(q.FilePath)
        q) // forward pipe the query
    |> deleteRowFrom db.Uploads

    // update the database
    saveToDb()

However, I generally wouldn't recommend doing something like this, as it introduces side-effects into the middle of a query. This is likely to make your code more difficult to reason about.

Instead, I would recommend assigning the query to a value with a let binding, and then pass it to Seq.iter to do all the operations with side effects, and reuse it in a query if you need to do that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top