What's the difference between controller first and choice first?

I see code in the docs written in both ways, is there a difference or a canonical way to do write this?


    controller owner can
        : ContractId Contact
          newTelephone : Text
          create this with
            telephone = newTelephone


    choice Sign : ContractId Pending with
        signer : Party
      controller signer
          -- Check the controller is in the toSign list, and if they are, sign the Pending contract
          assert (signer `elem` toSign)
          create this with alreadySigned = signer :: alreadySigned

Hi @anthony, there are two differences:

  1. The controller x can syntax implicitly adds x to the list of observers. For the second syntax, you have to add x to the list of observers separately.
  2. The second form is more general. Specifically, the controller expression can refer to the fields of your choice argument. You make use of that in your example above: The controller signer is only introduced by the choice argument. With the controller … can syntax, the controller expression can only refer to the fields of the template so you will get an error if you try to rephrase your second example using the controller … can syntax. You can find more information on that at https://blog.daml.com/daml-driven/daml-does-yoga-an-introduction-to-flexible-controllers

I hope that helps!


So for the second difference controller ... can cannot accept new arguments/fields but choice ... controller can?

Also: :moritz:

You can have fields in the choice argument with both syntaxes. What you cannot do is refer to the field in the controller expression. Here are 3 examples that hopefully make it clear:

template T
    p0 : Party
    signatory p0

    -- This is ok, the controller expression p0 does not refer to the choice argument
    controller p0 can
      A : ()
          p1 : Party
        do pure ()

    -- This is ok, the controller expression does refer to the choice argument but we use syntax 2
    choice B : ()
        p1 : Party
      controller p1
      do pure ()

    -- This is an error, the controller expression p1 refers to the choice argument but we use syntax 1
    controller p1 can
      C : ()
          p1 : Party
        do pure ()
1 Like