Expressions and operators

Operators

PPL provides the following operators:

Category Operators

Arithmetic

+, -, *, /

Append

&

Boolean

and, or, xor, not

Comparison

>#, >=, <#, <=

Value equality/inequality

=v, #v

Reference equality/inequality

=r, #r

Feature access

., .null?, .error?

if expression

if {expression} then {expression} else {expression}

Null alternative

if_null:

Error alternative

if_error:

Common precedence rules are built into PPL (e.g. multiplication before addition).

Operator overloading is supported in the following way: Some operators are implemented by a function with a defined name. For example, the compiler applies function multiply for operator *. Thus 3 * 4 is translated by the compiler to 3.multiply(4).

Therefore you can use these operators for your own types. For example, if you create a new type complex_number with functions add and multiply, you can use the operators + and * and benefit from the built-in operator precedence rules. Instead of writing …​

c4 = c2.multiply(c3).add(c1)

... you can simply write:

c4 = c1 + c2 * c3

The following table shows the built-in function names for operators that can be used in any type:

Operator Function name

+

add

-

subtract

*

multiply

/

divide

&

append

and

and

or

or

xor

xor

not

not

=v, #v

is_equal_to

>#, >=, <#, <=

compare_to

Examples of expressions and operators:

  • arithmetic operators

    // addition
    
    const a = 3 + 4     // with '+' operator
    assert a =v 7       // check result
    
    const b = 3.add(4)  // same with function call
    assert b =v 7
    
    // operator precedence
    
    assert 1 + 2 * 3 =v 7   // multiplication before additon
    assert (1 + 2) * 3 =v 9 // parenthesis used to change precedence
    assert 1 + 2 * 3   =v 1.add(2.multiply(3))
    assert (1 + 2) * 3 =v 1.add(2).multiply(3)
  • append operator

    const foo = "foo"
    const bar = "bar"
    const fb1 = foo & bar            // concatenation using '&' operator
    const fb2 = foo.append(bar)      // using function call
    const fb3 = """{{foo}}{{bar}}""" // using string interpolation
    
    assert \
        fb1 =v "foobar" and \
        fb2 =v "foobar" and \
        fb3 =v "foobar"
    
    const message = "Current time: " & local_time.now.to_string
    write_line ( message )
  • boolean operators

    const the_sun_shines = yes
    const it_rains = no
    const weather_is_fine = the_sun_shines and not it_rains
    assert weather_is_fine
  • comparison operators

    assert 7 =v 7 and 7 ># 6 and 7 >= 7 and 7 <# 8 and 7 <= 7
    
    const seven1 = 7
    const seven2 = 6 + 1
    assert seven1 =v seven2          // values are equal
    assert not ( seven1 #v seven2 )
    assert seven1 #r seven2          // but references are not
    assert not ( seven1 =r seven2 )
  • accessing an object’s feature (i.e. an attribute or a function)

    • without null or error check

      // function 'first' of type 'string' returns a character
      assert "abc".first =v 'a'
      
      assert "abc".first.to_string =v "a"
      
      assert "123456".substring ( from = 3, to = 4 ) =v "34"
      assert "12ab56".substring ( from = 3, to = 4 ).to_upper_case =v "AB"
    • with null check

      const index_1 = "abc".find_first ( "b" )
      assert index_1 is not null
      assert index_1 =v 2
      
      const index_2 = "abc".find_first ( "z" ) // function 'find_first' returns null
      assert index_2 is null
      
      // following instruction is not allowed because function 'find_first' can return null,
      // which would cause a null pointer error
      // const index_as_string = "abc".find_first ( "b" ).to_string
      
      // we have to check for null with the '.null?' operator
      const index_as_string = "abc".find_first ( "b" ).null?.to_string
      assert index_as_string is not null
      assert index_as_string =v "2"
      
      ///
          In the following instruction 'to_string' is not executed,
          because 'find_first' returns null.
          No null pointer error occurs!
          c is simply set to 'null'
      .///
      const c = "abc".find_first("z").null?.to_string
      assert c is null
      
      // We can also use an 'if null' instruction:
      const index_3 = "abc".find_first ( "z" )
      if index_3 is not null then
          write_line ( "found ")
      else
          write_line ( "not found ")
      .
    • with error check

      // Retrieve content from URL example
      // Note: By convention, functions that might return an error are prefixed with 'try_'
      
      const URL_string = "http://www.foo.com"
      
      const result = \
          URL.try_parse ( URL_string ) \
          .error? \
          .try_open_connection \
          .error? \
          .try_get_content_as_string
      
      ///
      The type of 'result' is 'string or error or null' (a union/sum type).
      If the URL is invalid or
          a connection cannot be established or
          the URL content cannot be retrieved
      then result contains an 'error' object
      else it contains a 'string' object, or 'null' if there is no content
      .///
      
      
      // Now we can check the result
      case type of result
          when string s
              write_line ( """The content of {{URL_string}} is: {{s}}""" )
          when error e
              write_line ( """Connecting to {{URL_string}} raised the following error: {{e.description}}""" )
          when null
              write_line ( """There are no data available at {{URL_string}}""" )
      .
  • if expression

    const height = 10
    const width = 20
    const size = if height >= 10 and width >= 15 then "big" else "small"
    
    assert size =v "big"
  • if_null operator

    // if 'get_name_or_null' returns null then "unknown" will be assigned to name
    const name = get_name_or_null if_null: "unknown"
    assert name is not null
    
    ///
    If the customer has no orders yet then
        - 'customer.order_list' returns null
        - 'size' is not executed
        - 0 (the expression after if_null:) is assigned to 'num_orders'
    else
        'num_orders' contains the number of elements in customer.order_list
    .///
    
    const num_orders = customer.order_list.null?.size if_null: 0
    
    write_line ( """Number of orders: {{num_orders.to_string}}""" )
  • if_error operator

    // If _any_ error occurs then "unknown" will be assigned to 'URL_content'
    const URL_content = \
        URL.try_parse ( "http://www.foo.com" ) \
        .error? \
        .try_open_connection \
        .error? \
        .try_get_content_as_string \
        if_error: "unknown"

results matching ""

    No results matching ""