Wiki

Expression Tour

This is a "tour" of various kinds of expressions in Cobra. It is intended to help you learn Cobra by quickly highlighting some interesting expressions you can write. It is neither a reference nor an exhaustive list of features. It assumes that the reader has basic familiarity with programming.

Displaying Expression Values

One of the best ways is to display an expression's value is to use the Trace statement which will show the source code of the expression, its value and the location of the trace in the source code (filename, line number, etc.):

trace p.x, p.y
    trace: p.x=5; p.y=6; at Foo.cobra:6; in Foo.main

You can, of course, use a Print statement. On a related note, you can validate the value of an expression with an Assert statement.

print 'My name is', name
assert x > 0

Arithmetic

Arithmetic has the usual infix operators and parentheses for grouping. Note that division with a single slash (/) gives a fractional value. Use a double slash (//) for "integer" division.

assert 4 / 5 = 0.8
assert 4 // 5 == 0
assert 6 / 5 == 1.2
assert 6 // 5 == 1

Augmented assignment operators can be used to change values:

i += 1
p.x *= 2

Underscores can be put in numbers to separate groups of digits for easier reading:

big = 10_000_000

Bitwise

Standard bit operations.

  • & = bitwise 'and'
  • | = bitwise 'or'
  • ~ = bitwise not (flip)
  • ^ = bitwise Xor
  • << = left shift
  • >> = right shift

Boolean

Boolean expressions include the literals true and false as well as logical operations such as and, or, not, comparisons and other tests.

obj.isActive = true
if obj.isActive, .doSomething

Note: You dont need to compare booleans against true or false ( dont say == true or ==false).
Most expressions can determine a natural truth or not. See ConditionalExpr.

to-do (all, any)

Strings

to-do (literals, immutable, common methods, stringbuilder, msdn reference)

Calling Methods

to-do (don't need empty parens, calling on "this", calling base)

Instantiating Types

to-do (use parens, keyword args for properties, combining enums, works on System.Type and dynamic)

Comparing Values

to-do (<>, is & is not vs. == & <>, 0<= i < 10, overriding .equals (and .getHashCode) and .compareTo)

Collections

to-do (list, array, set, dict, explicit creation, indexing, .get, membership(in and not in for lists, arrays, sets, dict.keys, dict.values) )

Slicing

to-do

Type Membership

to-do (inherits, implements, if-inherits, alternative is virtual method)

Casting to Type or Nilability

You can cast an expression to a particular Type (nilable or not) or cast to or away from nilability.

EXPR to TYPE

  • cast the expression to the given TYPE, cast failing throws an Exception.
  • ("cast or throw Exception")

EXPR to? TYPE

  • cast the expression to the given TYPE, if the cast fails return nil
  • ("cast or return nil")
  • Note: single token 'to?' no spaces between 'to' and '?'

EXPR to ?

  • cast the type of EXPR to the nilable version of same type (EXPR.typeOf?)
  • Note space between 'to' and '?'

EXPR to !

  • cast the type of EXPR to the non-nilable version of same type( EXPR.typeOf!)
s = 'String'
sObj = s to Object
assert sObj.typeof is Object

ds as dynamic = 'xyzzy'
s = ds to String

i = 99
s = i to? String
assert s is nil

s = 'xyzzy'  # nonnilable
sNil = s to ? #cast to nilable

s as String? = 'xyzzy'
sNotNil = s to ! # non nilable

# cast or nil
foo = oFoo to? BarType 
foo ?= defaultBar # nil coalesce nil foo to value of variable defaultBar

foo = oFoo to? BarType 
if not foo, print 'cast oFoo to BarType failed' 
# not foo same as foo == nil

If Expression

Provide an expression or alternate depending on whether a conditional-expression evaluates true or false Note: There can be no space between the if and the '(' - single token 'if('

i=22
z = if( i>10, 100, 0) 
assert z == 100

name = if( s.length, s, 'empty') # default name if zero length s

o = if(o, o, default)
# set o to 'default' if it is nil - but see nil coalesce below

see also IfExpression

For Expression

Apply an expression across a collection or range or a filtered subset thereof returning a new list.

a = for i in 1:4 get i*2
assert a == [2,4,6]

a = for i in [1, 2, 3] get i*10
assert a == [10, 20, 30]  

a = for i in 1:10 where i>5 get i
assert a == [6, 7, 8, 9]

c = ['how', 'now', 'brown', 'cow']
d = for k in c where k.endsWith('ow') get k
assert d == ['how', 'now', 'cow']


tmpFiles = for fileName in Directory.getFiles('.') where '.tmp' in fileName

see also ForExpression

Try-Catch-Get Expression

This is a shorthand for a try-catch statement wrapping a single expression that may throw an exception. The difference is that it allows an alternative expression to be provided if an Exception is thrown (rather than the Exception)

The value of the expression is the value of the expression following 'try' or if an exception is thrown the value of the expression after the 'get'.

If an Exception-Type is not given it will catch all Exceptions.

inVal = '..' #an int string presumably
x = try int.parse(inVal) catch FormatException get 0 #  return 0 if inVal not an int String

# Catch all exceptions
dflt = '---'
s1 = try String.format('{1:P}', 0.123) catch get dflt
assert s1 == '---'

Nil

Cobra has various operations and literals around nil/null values.

nil is the nil/null literal.

any as Insect? = nil  #type is Insect or nil

Cobra provides operators to allow coalescing of expressions that evaluate nil or non nil.
This saves an explicit nil comparison check and assignment in favor of a coalescing expression or an augmented assignment.

'?' is nil coalesce operator
'!' is non-nil coalesce operator

EXPR ? EXPR1

  • nil coalesce - if EXPR is nil return EXPR1

EXPR ! EXPR1

  • non-nil coalesce - if EXPR is non nil return EXPR1

augmented assignment uses '?=' and '!='

EXPR1 ?= EXPR1

  • nil coalesce EXPR1 to itself or EXPR2
  • same as EXPR1 = EXPR1 ? EXPR2

EXPR1 != EXPR1

  • non-nil coalesce EXPR1 to itself or EXPR2
  • same as EXPR = EXPR1 ! EXPR2
  • Note: gotcha Warning b != a This is NOT 'b not equals (<>) a' - is same as b = b ! a OR b = if( b <> nil, a, nil)
if a is nil, print 'Bad a' # explicit comparison and statement

y = a ? b    # coalesce nil : y gets a if a non nil, b otherwise
#same as y = if(a, a, b) except a evaluated only once

a = a ? default    # a if a nonnil, default otherwise
# above is same as 
a ?= default


y = b ! a    # coalesce non nil : y gets b if b is nil, a otherwise  
# same as y = if(b <> nil, a, nil)  OR y = if(not b, a, nil)

i as int? = input ! int.parse(input)  
#( equiv to i = if(input <> nil ? int.parse(input),  nil)

See also NilableTypes

Method References

to-do (ref obj.method)

Expressions in Contracts

to-do (old expr, a implies b, breakout to a method)

See Also