Version 8 (modified by hopscc, 11 years ago) |
---|
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 operations such as and, or, not, comparisons and other tests.
obj.isActive = true if obj.isActive, .doSomething
to-do (all, any, don't say ==true or ==false)
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
Cast an expression to a particular Type (nilable or not). 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
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
If Expression
Trinary operator on an expression. If the conditional expression evaluates to true give the first Expr otherwise give the second.
Note: no space between the if and the '(' - single token 'if('
Grammar
if( COND-EXPR, EXPR1, EXPR2 )
i=22 z = if( i>10, 100, 0) assert z == 100 name = if( s.length, s, 'empty') o = if(o, o, default) # set o to 'default' if it is nil - but see nil coalesce below
For Expression
Apply an expression across a collection or range or a filtered subset thereof.
Grammar
for VAR in EXPR [where EXPR ] get EXPR
for VAR in EXPR where EXPR
- same as for VAR in EXPR where EXPR get VAR
for VAR in START-EXPR : STOP-EXPR [: STEP_EXPR] [where EXPR] get EXPR
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 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
Try-Catch-Get Expression
This is a shorthand for a try-catch statement wrapping a single statement assigning an expression.
The value of the expression is the value of the expr 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.
Grammar
try EXPR catch [ EXCEPTION-TYPE ] get EXPR
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
Operations and literals around nil/null values.
nil is the nil/null literal
EXPR to ?
- cast the type of EXPR to the nilable form of the same type (EXPR.typeOf?, nilable EXPR.typeof)
EXPR to !
- cast the type of EXPR to the the non-nilable form of same type( EXPR.typeOf!)
EXPR ? EXPR1
- nil coalesce - if EXPR is nil return EXPR1
EXPR ! EXPR
- non-nil coalesce - if EXPR is non nil return EXPR1
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' 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)
Method References
to-do (ref obj.method)
Expressions in Contracts
to-do (old expr, a implies b, breakout to a method)