corbyn3
corbyn3

Reputation: 97

Incorrect indentation for a lambda function

I am doing a direct combination of 2 functions using a lambda function. Because indentation is a problem I am doing direct copy/paste from Visual Code:

version 1 of the function is:

module myrun = 
...
    let mywrite(price: string, volume: string, time:string) =
        use cmd99 = new SqlCommandProvider<"INSERT INTO swirepacific(ric, price, volume, inst, ttime, views, strike, etime) VALUES (@st1, @st2, @st3, @st4, @st5, @st6, @st7, @st8)", connStr>(connStr)
        cmd99.Execute(st1=myric,st2=float price,st3=int volume,st4=inst,st5=System.DateTime.Parse time, st6 = myview, st7 = strike, st8=System.DateTime.Parse etime)
        |> ignore

    let toDB (data:seq<IData>) =
        data 
        |> Seq.map (fun (r:IData) -> (r.AllFields.["VALUE"].ToString(),r.AllFields.["VOLUME"].ToString()
        ,r.Timestamp.Value.ToString("yyyy-MM-dd hh:mm:ss.fff")))
        |> Seq.iter mywrite

Version 1 is a write to database code. It uses SqlCommandProvider to parse a SQL statement directly. The problem with version 1 is that while it accepts price, volume and time from previous functions, the myric, inst, strike and etime are Global Variables.

With version 2, I want to skip global variables completely and take all inputs as parameters. It should be a better practice and pretty much required if I want to run the functions in parallel:

Version 2 of the function is

module myrun = 
...
    let toDB2 (data:seq<IData>, aric: Aric, ainst: Ainst, astrike: Astrike, aetime: Aetime) =
        data
        |> Seq.map (fun (r:IData) -> (r.AllFields.["VALUE"].ToString(),r.AllFields.["VOLUME"].ToString(),r.Timestamp.Value.ToString("yyyy-MM-dd hh:mm:ss.fff")))
        |> Seq.iter (fun (price, volume, time) -> 
                (use cmd99  = new SqlCommandProvider<"INSERT INTO swirepacific(ric, price, volume, inst, ttime, views, strike, etime) VALUES (@st1, @st2, @st3, @st4, @st5, @st6, @st7, @st8)", connStr>(connStr)
                cmd99.Execute(st1=aric,st2=float price,st3=int volume,st4=ainst,st5=System.DateTime.Parse time, st6 = myview, st7 = astrike, st8=System.DateTime.Parse aetime) 
                |> ignore)

There is a red line under the let in "let toDB2". The error is Incomplete value or function definition. If this is an expression, the body of the expression must be indented to the same column as the 'let' keyword

I suspect it has something to do with the indentation of the lambda function.

Can you please help me? Thanks!

Upvotes: 0

Views: 77

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243061

The answer from @Aron shows how to correct your code without changing its structure. However, I think that there is not much benefit in using functions like map in your particular case.

You are essentially writing imperative bit of code that iterates over some data and writes it to a database. This performs IO and so it is inherently imperative - in such cases, I often find it easier to write a more imperative style of F# - the nice side effect of doing this is that anyone reading the code will immediately see that it is, in fact, imperative and will not confuse it with some functional data processing.

So, my version would actually remove all lambdas from this snippet:

module myrun =

  [<Literal>]
  let InsertQuery = 
    "INSERT INTO swirepacific(ric, price, volume, inst, ttime, views, strike, etime)
     VALUES (@st1, @st2, @st3, @st4, @st5, @st6, @st7, @st8)"

  let toDB2 (data:seq<IData>, aric: Aric, ainst: Ainst, astrike: Astrike, aetime: Aetime) =
    for r in data do
      let price = r.AllFields.["VALUE"].ToString()
      let volume = r.AllFields.["VOLUME"].ToString()
      let time = r.Timestamp.Value.ToString("yyyy-MM-dd hh:mm:ss.fff")
      use cmd99  = new SqlCommandProvider<InsertQuery, connStr>(connStr)
      cmd99.Execute
        ( st1=aric,st2=float price,st3=int volume,st4=ainst,st5=System.DateTime.Parse time, 
          st6 = myview, st7 = astrike, st8=System.DateTime.Parse aetime) |> ignore

Upvotes: 1

Aron
Aron

Reputation: 9246

I think you're just missing a single closing parenthesis. I just added one at the end to close your 2nd lambda expression and the compiler is happy:

module myrun =

    let toDB2 (data:seq<IData>, aric: Aric, ainst: Ainst, astrike: Astrike, aetime: Aetime) =
        data
        |> Seq.map (fun (r:IData) -> (r.AllFields.["VALUE"].ToString(),r.AllFields.["VOLUME"].ToString(),r.Timestamp.Value.ToString("yyyy-MM-dd hh:mm:ss.fff")))
        |> Seq.iter (fun (price, volume, time) -> 
                (use cmd99  = new SqlCommandProvider<"INSERT INTO swirepacific(ric, price, volume, inst, ttime, views, strike, etime) VALUES (@st1, @st2, @st3, @st4, @st5, @st6, @st7, @st8)", connStr>(connStr)
                cmd99.Execute(st1=aric,st2=float price,st3=int volume,st4=ainst,st5=System.DateTime.Parse time, st6 = myview, st7 = astrike, st8=System.DateTime.Parse aetime) 
                |> ignore))

Upvotes: 2

Related Questions