If-Then-Else statements inside forA loop in DAML

Hi @Pris17,

First off, for better or worse, the Daml language is “whitespace-sensitive”, which in this case means that indentation is used to delimit blocks of code. Lines of code that are supposed to be part of the same block must start at the same offset (i.e. be preceded by the same number of spaces), and nested blocks must be indented more than their enclosing block.

So, for example:

  let c = 1
      d = 2

is valid, but

  let c = 1
       d = 2

is not because c and d need to be aligned.

Another example:

  let i = case mi of
       None -> 0
       Some x -> x

is valid, but

  let i = case mi of
      None -> 0
      Some x -> x

would not be, because the None and Some lines are supposed to start nested blocks and thus need to be indented more than the i.

Daml does not have variables; what it does have is bindings. A binding is a way for an enclosing block to define a shorthand name to be used in a nested block. Bindings can never escape their enclosing block.

The one exception to this is do notation, which is special in that it allows one to define bindings within the current block, to be used at any point after their definition (but still only within the current block, i.e. anything as indented or more indented than the line on which the binding is introduced).

Constructs that introduce new bindings also introduce nested blocks where those bindings are defined. For example, the let ... in construct:

fib : Int -> Int
fib n = case n of
  0 -> 0
  1 -> 1
  n -> if n < 0
       then 0
       else let n1 = fib (n - 1)
            in let n2 = fib (n - 2)
               in n1 + n2

defines a binding that can only get used in the block introduced by in. In a way, you can imagine that you have parentheses (and this is in fact valid Daml) like so:

fib : Int -> Int
fib n = case n of
  0 -> 0
  1 -> 1
  n -> if n < 0
       then 0
       else (let n1 = fib (n - 1)
             in (let n2 = fib (n - 2)
                 in (n1 + n2)))

and that the binding defined by let is only available within the set of parentheses that being immediately after in.

So, in your code sample:

               do forA otherParties (\dv -> 
                    do
                      (cID, dvContract) <- fetchByKey @ContractB (dv, id)
                      -- From here on out, cID and dvContract exist,
                      -- until the close paren of the enclosing do
                      if (show dv == "PartyC") then do
                        
						let a = dvContract.abc
                            -- From here on out, a exists
							b = dvContract.def
                            -- From here on out, b exists
                            -- a and b no longer exist after this line
                      else if (show dv == "PartyD") then do
                        let c = devSecCon.ghi
                            -- From here on out, c exists
                            d = devSecCon.jkl
                            -- From here on out, d exists
                            -- c and d no longer exist after this line
                ) -- cID and dvContract no longer exist
                -- none of cID, dvContract, a, b, c, or d exist here
				create ContractA with a= a; b= b; c= c; d= d; ..

Hope this helps.

2 Likes