= Nilable Types = Cobra does 'nil tracking' which forces specification of variables that may be allowed to contain '''nil'''.[[BR]] This is done to * Help eliminate runtime exceptions about nil reference errors * Allow reporting of multiple nil referencing errors at compile time (instead of a single failure point at runtime) * Help document which parameters permit nil and which do not '''nil tracking''' is done by typing the variable as a nilable Type which is by typing to any typeName with a '''?''' suffix e.g. {{{ str as String = "Mystring" # str can only have a String value strN as String? # strN may have a String value OR nil lazyType as Type? # Type OR nil }}} nilable Typing can be applied to anything that can be Typed ( local variables, class variables Args and returnTypes) {{{ def sendWelcome(cust as Customer, referral as Customer?) # will not accept nil for `cust` # will accept nil for `referral` }}} == Casting to and From nilable Types == Sometimes it is necessary to cast an existing typed variable to a nilable type [[BR]] ( e.g for receiving results of a library call) or [[BR]] to cast a nilable type to its non nilable type (when you've ascertained its not nil and the receiver only takes a non nilable type) There is a shorthand for both of these Casting to a nilable version of an existing type to ? Casting away from nilable version to ! e.g. {{{ s as String = 'a string' sn = s to ? # sn is String? assert sn s1 = sn to ! # s1 is String - may not get nil }}} == nil and not nil detection == You can explicitly test for nil or not nil values using normal conditionals (true is non-nil) {{{ s as String = 'sss' assert s if s print 's not nil' sn as String? = nil assert not sn if not sn print 'sn is nil' }}} == nil and non-nil coalesce == There are shortcuts for Nil test and assign default (coalesce) or non nil test and process [[BR]] '''a ? b''' coalesce to b if (a) nil.[[BR]] The expression evaluates to a unless that value is nil, in which case, it evaluates to b.[[BR]] Neither expression will be evaluated more than once and if the first expression is non-nil then b will not be evaluated at all.[[BR]] ( Also the direct augmented assignment version '''a ?= b''' a gets b if a is nil ) '''a ! b ''' evaluate b if a not nil. {{{ stuff as String? = nil defaultStuff='DEFAULT' stuff = stuff ? defaultStuff # coalesce nil # OR stuff ?= defaultStuff # equivalent to stuff = if (not stuff, defaultStuff, stuff) # or # if not stuff # stuff = defaultStuff assert stuff == defaultStuff def doSomething(input as String) if input # detect not nil print 'Received some input.' i as int? = input ! .parse(input) # execute non-nil # equiv to # i = if(input, .parse(input), input) # an alternative would also be: # input = input ? '0' # i as int = .parse(input) }}}