Template Modification Fails on Template Role

Reference: GitHub - digital-asset/boat

Am modifying the Boat example with the goal of initially substituting ‘making a Boat’ to ‘planting a Pine Tree’. Once that all works, I’ll modify the Custody and Transfer roles into something more germane. Currently the only sticking point seems to be in the template ManufacturerRole.

template ManufacturerRole
template ManufacturerRole
  with 
    manufacturer: Party
    coastGuard: Party 
    operator: Party 
  where 
    signatory operator
    observer coastGuard 

    controller manufacturer can 
      nonconsuming Manufacture: ContractId Boat
        with 
          name: Text
        do 

Exchanging the terms manufacturer, coastGuard, and operator for seedling_planter, forest_compliance, and forest_operator works OK.

Seedling_PlanterRole
template Seedling_PlanterRole
  with 
    seedling_planter: Party
    forest_compliance: Party 
    forest_operator: Party 
  where 
    signatory forest_operator
    observer forest_compliance

    controller seedling_planter can 
      nonconsuming seedling_planter: ContractId Tree 
        with 
          name: Text
        do

The error from daml start is:

Range:    94:19-94:35
Source:   parser
Severity: DsError
Message:  daml/Main.daml:94:20: error:parse error on input ‘seedling_planter’
ERROR: Creation of DAR file failed.

Line 94 being: nonconsuming seedling_planter: ContractId Tree

However with the template below, I cannot get my head around what the seedling_planter equivalent for the non-consuming Manufacture should be.

The error is due to capitalization. Choice names need to be calitalized. I’d think that Plant_Seedling is to seedling_planter what Manufacture is to manufacturer so maybe go for nonconsuming Plant_Seedling : ContractId Tree in line 94.

2 Likes

Choice names are types (records, under the hood) and thus must start with a capital letter. You’re also missing a keyword, which is more likely the immediate issue here: nonconsuming must be followed by choice; as in

EDIT: As @bernhard kindly pointed out in private, I missed the use of the controller can syntax, which does not include the choice keyword.

1 Like

Thank you @bernhard und @Gary_Verhaegen :+1:t2:

Now have:

  • seedling_planter instead of manufacturer (Noun)
  • Plant_Seedling instead of Manufacture (Verb)
  • Removed two instances on boat that were in the Main.daml :man_facepalming:t2:
  • Removed duplicate -- forest_compliance = forest_owner
Works now with the exception on a single error.
SDK 1.15.0 has been released!
See https://github.com/digital-asset/daml/releases/tag/v1.15.0 for details.

SDK 1.15.0 has been released!
See https://github.com/digital-asset/daml/releases/tag/v1.15.0 for details.

Compiling tree to a DAR.
File:     daml/Main.daml
Hidden:   no
Range:    50:14-50:27
Source:   typecheck
Severity: DsError
Message:  daml/Main.daml:50:15: error: Not in scope: ‘newCompliance’
ERROR: Creation of DAR file failed.
daml-helper: Received ExitFailure 1 when running
Shell command: /home/quid/.daml/bin/daml build

Line 50 newCompliance = owner

However I am not using the term Compliance but forest_compliance`

I think that using hyphenated_words presents syntax-related issues, and that perhaps hyphenatedwords might be a better idea.

Can you share the code you’re using now that produces this error?

As for snake_case vs camelCase both are perfectly fine from a syntax pov. In Haskell, the convention is to use camelCase and we borrowed that for Daml so the standard library uses that consistently and I’d generally recommend to not deviate from that but it’s only a convention. Everything will work perfectly fine if you use snake_case for your own identifiers.

1 Like

I personally prefer snake_case and use it liberally in both Daml and Haskell (at least when I don’t need to share it; if I’m writing a library, I follow community conventions); not only do I find snake_case easier to read, I also quite like the fact that my identifiers are distinguishable at a glance from library identifiers.

Either way, the part the compiler cares about is that value identifiers start with a lowercase and type (and module) identifiers start with an uppercase. After that you can mix and match underscores, letters and numbers in any combination you see fit.

Your error message seems fairly consistent with your explanations, actually. What it seems to say is that, on line 50, you have

  newCompliance = owner

and that is invalid because newCompliance does not exist in the current scope. You tell us you’re using forest_compliance as an identifier, so it’s not very surprising that newCompliance does not exist.

If that line is expected to introduce a new identifier, the syntax is incorrect. Depending on context, it must be either (in a do block, if right-hand-side is an action)

newCompliance <- someActionOf owner

or (in a do block, if right-hand-side is a pure value)

let newCompliance = owner

or (outside of a do block`)

let newCompliance = owner
 in ...

The line newCompliance = owner could be valid syntax for introducing a new binding, but only in the context of a where clause, and if that were the context you’re in, it wouldn’t be reporting an error.

The other possibilities I can see are:

  • You want to do a comparison rather than introduce a new binding; in that case, you want == instead of =.
  • You are trying to assign a value to the field of a record, in which case you need to change newCompliance to instead be the name of the field in that record (perhaps that is forest_compliance?).

As @cocreature mentioned, it would be a lot easier to help you if you provided a bit more context than the single failing line.

1 Like