Open bjartek opened 2 years ago
Thank you for pointing this out! This is correct behaviour, as, all function arguments are always eagerly evaluated, I see the problem here though.
Other languages solve this in various
@autoclosure
annotation: https://developer.apple.com/documentation/swift/assert(_:_:file:line:).
The autoclosure annotation automatically turns arguments into a function. This means that the message is only evaluated when the message parameter function is called, not eagerly.=>
): https://www.scala-lang.org/api/2.13.6/scala/Predef$.html#assert(assertion:Boolean,message:=%3EAny):Unit
Similar to Swift, this means that the message is only evaluated when needed, not eagerly.Adding support for auto-closures or call-by-name seems like a lot of effort, for mostly this particular use-case.
Maybe we could adopt Kotlin's solution, i.e. change the message
parameter to lazyMessage: ((): String)
, e.g. the example above would be:
assert(true, lazyMessage: fun (): String { return "foo".concat("bar") })
That's quite a lot more boiler-plate code though. We could maybe add sugar for function literals:
assert(true, lazyMessage: () => "foo".concat("bar"))
On post conditions before has weird behavior too.
false || before(self.getBalance())>=0 calls getBalance, I know the reason but looks little strange
Oh btw @autoclosure seems to be the elegant way to do this in my opinion. Backwards compatible. Basically rewriting ast to if !assert(expression) { panic(message) }
Nice to have, not a stable Cadence blocker
The code above will never trigger, but it will still add computation since we have to evaluate the message.