Hi all,

FPC trunk (3.3.1) now supports statement expressions. You can use if, case and try..except as expressions that return a value.
Big thanks to Frederic Kehrein who implemented most parts.

Enabling

{$modeswitch StatementExpressions}

The modeswitch is on by default in {$mode delphi} and {$mode delphiunicode}. All other modes, including objfpc, need the modeswitch.


if-expression

s := if Count > 0 then 'some' else 'none';

s := if i < 10 then 'small' else
     if i < 100 then 'medium' else
     'large';

DoSomething(if Verbose then LogLevelDebug else LogLevelInfo);

- The else part is required.
- Only the selected branch is evaluated.
- The else branch extends as far to the right as possible, so if b then 'A' else 'B' + 'C' means if b then 'A' else ('B' + 'C'). To use the result in a larger expression, put the if-expression in brackets:

i := (if b then 10 else 20) + 1;


case-expression

s := case Color of
  clRed:   'red';
  clGreen: 'green';
  else     'other'
end;

- It must end with end.
- It must cover every possible value. Either the labels cover the whole ordinal range, e.g. all enum values or False/True, or there is an else/otherwise branch. If neither holds, you get "Statement expression does not handle all cases".
- Ranges (1..9:) and string case labels work as they do in case statements.
- The semicolon before else and before end is optional.


try..except-expression

n := try StrToInt(s) except -1 end;

s := try LoadName(Id)
     except
       on E: EFileNotFound do '<missing>';
       else '<error>'
     end;

- If there are on-do handlers, an else branch is required so that every exception produces a value.
- try..finally cannot be used as an expression.


Result type

The branches must be type-compatible. The result has their common type, e.g.:

- ShortString + UnicodeString gives UnicodeString.
- Two sibling classes give their common ancestor.
- A class + nil gives that class.
- A string + Variant gives Variant.

Overload resolution works on the result type. For example, Fly(if b then 1.5 else 2.5) selects the same overload as Fly(1.5).

Incompatible branches give an error, e.g. if b then 'Foo' else 32.


Nesting and anonymous functions

Statement expressions can be nested, and a branch can be an anonymous function. The target must be a procedure variable or a reference to type:

{$mode delphi}
var
  Handler: TProc;
begin
  Handler :=
    if Debug then
      procedure begin WriteLn('debug'); end
    else
      procedure begin end;


Enjoy!

Mattias

_______________________________________________
fpc-pascal maillist  -  [email protected]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to