Lazarus

Free Pascal => General => Topic started by: guest58172 on February 03, 2016, 02:24:16 pm

Title: Q about new IfThen() intrinsic
Post by: guest58172 on February 03, 2016, 02:24:16 pm
Hello, i've just read this:

http://lists.freepascal.org/pipermail/fpc-pascal/2016-January/046375.html

which basically announces that something like C ternary expressions is implemented in FPC trunk.

Will it work with += and -=, when C-like operators are activated ?
Title: Re: Q about new IfThen() intrinsic
Post by: Thaddy on February 03, 2016, 03:13:16 pm
What is that a F*...
Just try... You are a grown up boy.
Title: Re: Q about new IfThen() intrinsic
Post by: FTurtle on February 03, 2016, 03:47:53 pm
See options:
Project Options | Compiler Options | Parsing
Title: Re: Q about new IfThen() intrinsic
Post by: guest58172 on February 03, 2016, 05:24:29 pm
What is that a F*...
Just try... You are a grown up boy.
Calm down man, or take your little pills, It's just a question
Title: Re: Q about new IfThen() intrinsic
Post by: Zoran on February 03, 2016, 07:03:52 pm
What is that a F*...
Just try... You are a grown up boy.

He can just ask questions, this is a very interesting new language feature.
I believe that for talking about new beautiful feature, we are not required to install FPC from trunk.
Title: Re: Q about new IfThen() intrinsic
Post by: FTurtle on February 03, 2016, 09:17:21 pm
Sorry, first I wrong read and understood your question.

Quote
Since it's declared in the System unit it won't interfere with the
IfThen()s that are declared in the Math unit or other units, so they'll
continue to work as before to avoid any surprises.

So, now already available IfThen in few modules.

Write:

Code: Pascal  [Select][+][-]
  1. uses math, strutils;
and use them.

As far I understand Sven said about other feature.
It also will function (in System) and work similar.
I think C-like operators can not affect the ability to work of IfThen, because they are just another way of representation of the same things.
At least IfThen from strutils works with +=

Just for fun:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   a: Integer;
  4.   s: String;
  5. begin
  6.   a := StrToInt(Edit2.Text);  // initial value is 2
  7.   s := Edit3.Text;
  8.  
  9.   a *= 2;
  10.   s += Format('(%d%s25) ', [a, IfThen(a>25, '>', '<=')] );
  11.  
  12.   Edit2.Text := IntToStr(a);
  13.   Edit3.Text := s;
  14. end;
  15.  

Output to Edit3:

Code: Pascal  [Select][+][-]
  1. (4<=25) (8<=25) (16<=25) (32>25) (64>25)
  2.  
Title: Re: Q about new IfThen() intrinsic
Post by: BeniBela on February 03, 2016, 10:31:48 pm
Good thing I just installed fpc trunk.

Seems to work nicely

BUT

Code: [Select]
uses math;
ifthen(true, a,b )

evaluates both branches

What is planned for that?

It is quite unfortunately named, if it gets overriden by the math functions
Title: Re: Q about new IfThen() intrinsic
Post by: Blaazen on February 03, 2016, 10:37:11 pm
You didn't read the discussion on ML properly (no wonder, it's a few hundred posts  :)). Sven Barth already promised renaming to avoid confusion with Math.IfThen.
Title: Re: Q about new IfThen() intrinsic
Post by: FTurtle on February 03, 2016, 11:09:08 pm
Good thing I just installed fpc trunk.

Functions from math and strutils work in 3.0.0 (may be earlier), so, you could use existing installation of Lazarus 1.6 RC2 if it is.

BUT

Code: [Select]
uses math;
ifthen(true, a,b )

evaluates both branches

This is a fee for convenience. IfThen does not replace usual if, but it can be very useful in some cases, like in my example.

It is quite unfortunately named, if it gets overriden by the math functions

Why? First, the compiler will attempt to use functions from modules connected via Uses and if not found suitable, will use the new feature. As far as I understand, the main difference between them is:

Quote
function IfThen(Condition: Boolean; ThenExpr, ElseExpr: type): type;
...
An important point to note is that in general the result type is
determined by the ThenExpr (there are a few usability exceptions
regarding strings and chars).
Title: Re: Q about new IfThen() intrinsic
Post by: bee on February 04, 2016, 02:31:28 am
Oh God… not again! We already have had hundreds of email about this on the list. :D
Title: Re: Q about new IfThen() intrinsic
Post by: skalogryz on February 04, 2016, 03:42:41 am
Oh God… not again! We already have had hundreds of email about this on the list. :D
Indeed. This is how a technical non-problem turns into a political dispute.

The proposed IfThen() aka iif() aka iff() aka IfThenElse() intrinsic is supposed to act differently, than existing Math.IfThen. The key difference, is that only one of the expressions is evaluated, based on the value of condition. If condition is true, only "then" expression is evaluated (and returned), if condition is false, only "else" expression is evaluated.

But here comes the problem:
The intrinsic looks like a function, but acts differently. In case of a function all arguments are evaluated prior to the function call. That might cause confusion, even though there're already intrinsic that're acting in a similar manner, i.e. assert().

Logically, it's better to have as less exceptions as possible, that's why it is desirable not to add another exception into RTL.

So, in the thread another proposal came up - let's have if..then as an expression. That would make if..then an operator. With implementing this, a code like
Code: [Select]
  x:=if a then b else c;
would be possible. It might look nice, but ...

whenever a new operator is introduced, it must have a defined precedence. For example, what the value of x would be:
Code: [Select]
  x:=if true then 5 else 3 + 4;
should it be resolved as:
Code: [Select]
  x:=(if true then 5 else 3) + 4;
or
Code: [Select]
  x:=(if true then 5 else (3 + 4));
If using intrinsic, is really not a problem, since function call (which it looks like) takes the higher precedence:
Code: [Select]
  x:=IfThen(true, 5, 3)+4;
So defining the right precedence is critical to usability of an operator, since it might be a source for potential bugs.
But adding a new operator with its precedence opens a big can worm.
First of all, it breaks Pascal fundamental simplicity.
Pascal has only 4 (or 5 levels) of precedence (http://www.freepascal.org/docs-html/ref/refch12.html).
Compare it to C with 18 or even Algol with 12 levels.
More levels, the harder expressions are to be understood and read.
Secondly, it also creates precedent of extending the language with a new operator, so more operators could be added (case-expression... and so on). More operators -> greater complexity.
Thirdly, potentially one might start asking about overloading these new operators, bringing even more complexity.

Another point was made, that neither Ifthen() intrinsic nor if-expression solves any technical problems.
What they do could be achieved by using if-statement. So they're nothing more but a syntax sugar (not very welcomed, in general (http://freepascal.org/faq.var#extensionselect), that is intended to make the development a little bit easier (less typing, easier to port C-like language  code)

There's a saying: the road to hell is paved with good intentions. Is this case the sample of the saying?

What makes it all hard (over 200 emails of the mailing list), is that the patch has already been provided, it's very easy to accept it technically.
The optimal solution might be - not to do anything. Put the patch on hold, until the language is ready for it or until Delphi implements it also. (I wonder if Delphi developers had the same problem and decided not to add it to the language)

thanks for reading, btw!
Title: Re: Q about new IfThen() intrinsic
Post by: Martin_fr on February 04, 2016, 04:14:12 am
But here comes the problem:
The intrinsic looks like a function, but acts differently. In case of a function all arguments are evaluated prior to the function call. That might cause confusion, even though there're already intrinsic that're acting in a similar manner, i.e. assert().

Logically, it's better to have as less exceptions as possible, that's why it is desirable not to add another exception into RTL.

So, in the thread another proposal came up - let's have if..then as an expression. That would make if..then an operator. With implementing this, a code like
Code: [Select]
  x:=if a then b else c;
would be possible. It might look nice, but ...

whenever a new operator is introduced, it must have a defined precedence. For example, what the value of x would be:

There is also a point missing:

* IfThen() looks like a function, but is not. True.

But
* x:=if a then b else c;  the right hand site expression, looks like a statement, but isn't.

So in that, they both have the same problem, they are not what they look like.

Furthermore, if I understand the patch for the ":= if then else" correct (and I might not), then it is not actually implemented as operator.

The parser still parses the same "if" as before. All other operators are known as operator in the parser, and translated as such. There also is no entry in the operator precedence table. There simple is code that detects the "if" token, if in place of an operand.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode objfpc}
  3.  
  4. const a = 1 + 2;    // + is an operator, this works
  5. //const a = ifthen(true, 1,2);  // this does not work
  6. //const a = if true then 1 else 2;  // and this (despite it should be an operator) does not work either
  7.  
  8. begin
  9.   writeln(a);
  10.   readln;
  11. end.
  12.  
Title: Re: Q about new IfThen() intrinsic
Post by: guest58172 on February 04, 2016, 07:05:50 am
Hello, i've just read this:

http://lists.freepascal.org/pipermail/fpc-pascal/2016-January/046375.html

which basically announces that something like C ternary expressions is implemented in FPC trunk.

Will it work with += and -=, when C-like operators are activated ?

I just wanted to know if it was really comparable to the ternary operator:

Code: D  [Select][+][-]
  1. void main()
  2. {
  3.     int a,b,c,d;
  4.     a = (b == 0) ? c : d;       // a := IfThen(b=0,c,d);
  5.     a += (b == 0) ? c : d;      // a += IfThen(b=0,c,d);
  6. }
Title: Re: Q about new IfThen() intrinsic
Post by: mse on February 04, 2016, 09:39:36 am
What makes it all hard (over 200 emails of the mailing list), is that the patch has already been provided, it's very easy to accept it technically.
The optimal solution might be - not to do anything. Put the patch on hold, until the language is ready for it or until Delphi implements it also. (I wonder if Delphi developers had the same problem and decided not to add it to the language)
Yup. There are too much such constructs in Free Pascal already. That is why I started the MSElang initiative.
Title: Re: Q about new IfThen() intrinsic
Post by: Zoran on February 04, 2016, 11:16:55 am

Thank you, Bart, for this feature!

The optimal solution might be - not to do anything.

Oh, no... we came so close to have this nice language feature just to see that it might not get inculded...

Put the patch on hold, until the language is ready for it

until the language is ready - I do not understand when and how do you think the language can become more ready for this feature? As time passes, I do not see what can happen to ease these problems with function implemented in strutils and math -- they will still be there and behave like functions behave, always evaluate both branches and make side effects.

I hope that we will see it in FPC as soon as possible, that is in the next release.
Of course, it is a matter of taste. I feel free to talk about it here now. I don't use IfThen functions implemented in strutils and math, but the intrinsic in system unit is something I would use a lot. The name can be changed, but even that is not really necessary (Yes I read the discussion on mailing list, and this is still my opinion).

or until Delphi implements it also. (I wonder if Delphi developers had the same problem and decided not to add it to the language)

Please do not wait for Delphi. Let's not care about Delphi for once. And if Delphi doesn't implement it, we do not lose compatibility with Delphi code. Only the other way is lost -- FPC code with this cannot be ported to Delphi, but let them care about this.
Title: Re: Q about new IfThen() intrinsic
Post by: FTurtle on February 04, 2016, 12:46:37 pm
skalogryz, Martin_fr, thanks.
Title: Re: Q about new IfThen() intrinsic
Post by: Zoran on February 04, 2016, 01:34:58 pm
An argument for IIF:

In this mail: http://lists.freepascal.org/pipermail/fpc-pascal/2016-February/046444.html (http://lists.freepascal.org/pipermail/fpc-pascal/2016-February/046444.html) Maciej argues that IIF should not be used because in other languages it is implemented as a function which evaluates both branches.

Actually, not in all languages. It is defined so in VisualBasic. However, in Firebird it does what we need, it is implemented as (see here): (http://www.firebirdsql.org/refdocs/langrefupd25-intfunc-iif.html)
Quote
IIF(Cond, Result1, Result2) is a shortcut for “CASE WHEN Cond THEN Result1 ELSE Result2 END”. You can also compare IIF to the ternary “? :” operator in C-like languages.
So, it behaves just as our new intrinsic.
Title: Re: Q about new IfThen() intrinsic
Post by: FTurtle on February 04, 2016, 02:08:44 pm
By the way, good name for new intrinsic: IfThenGet

Code: Pascal  [Select][+][-]
  1. x := IfThenGet(c, a, b);

Title: Re: Q about new IfThen() intrinsic
Post by: skalogryz on February 04, 2016, 02:43:33 pm
Put the patch on hold, until the language is ready for it

until the language is ready - I do not understand when and how do you think the language can become more ready for this feature?
Recently generic were implemented for functions. That pretty much opened the door to implementing the IfThen() via regular language feature rather than a compiler intrinsic. Though there were an issue Silvio ran into. (Note: reporting the issue actually inspired compiler - intrinsic solution).
Another potentially possible approach is to have an inline function modifier to be evaluated on the first use, rather than prior to the call (as it is done right now). It would make inline functions to act similar to achieve the same functionality. However, implementing such argument modifier could be really tricky.
...who knows what other language features could be introduced, that would help to implement IfThen()

I hope that we will see it in FPC as soon as possible, that is in the next release.
Does it actually prevents you from completing your project? :)
Title: Re: Q about new IfThen() intrinsic
Post by: Zoran on February 04, 2016, 03:28:50 pm
Recently generic were implemented for functions. That pretty much opened the door to implementing the IfThen() via regular language feature rather than a compiler intrinsic. Though there were an issue Silvio ran into. (Note: reporting the issue actually inspired compiler - intrinsic solution).
Another potentially possible approach is to have an inline function modifier to be evaluated on the first use, rather than prior to the call (as it is done right now). It would make inline functions to act similar to achieve the same functionality. However, implementing such argument modifier could be really tricky.
...who knows what other language features could be introduced, that would help to implement IfThen()

We have a nice solution which can be included now. Why would we wait for other ways of implementing this? Why do you think that intrinsic solution should be avoided?

I hope that we will see it in FPC as soon as possible, that is in the next release.
Does it actually prevents you from completing your project? :)

Of course I can use good old if-then-else construct, but I would like to be able to use this nice new syntax.
Title: Re: Q about new IfThen() intrinsic
Post by: frakno on February 04, 2016, 04:30:14 pm
I do not understand the excitement. I use the following easy function, and I think that is meant by this discussion

Code: Pascal  [Select][+][-]
  1. function IfFork( Decision  :Boolean; YesInt  :Integer; NoInt  :Integer = 0 )  :Integer;
  2.   begin
  3.       if Decision then Result := YesInt else Result := NoInt;
  4.   end;
  5.  
  6. function IfFork( Decision  :Boolean; YesStr  :String; NoString  :String = '' )  :String;
  7.   begin
  8.       if Decision then Result := YesStr else Result := NoString;
  9.   end;
  10.  
  11. ...
  12.  

And the usage:
Code: Pascal  [Select][+][-]
  1. AString := IfFork(  SortType.ItemIndex = 0, 'ASC', 'DESC' );  

so why the big discussion about a built-in version
                         
Title: Re: Q about new IfThen() intrinsic
Post by: skalogryz on February 04, 2016, 04:39:02 pm
I do not understand the excitement. I use the following easy function, and I think that is meant by this discussion

Code: Pascal  [Select][+][-]
  1. function IfFork( Decision  :Boolean; YesInt  :Integer; NoInt  :Integer = 0 )  :Integer;
  2.   begin
  3.       if Decision then Result := YesInt else Result := NoInt;
  4.   end;
  5.  
         
You do understand that the following code
Code: [Select]
  b := true;
  a := IFFork (b, 5 + 5, 3-2);
does a useless job of calculating 3-2, since only 5+5 should be evaluated?

For example, this code
Code: [Select]
  b := true;
  if b then
    a := 5+5
  else
    a:= 3-2;
doesn't have such deficiency.

The all excitement is about having IfFork() that would be as effective as a plain if-statement.
Title: Re: Q about new IfThen() intrinsic
Post by: frakno on February 04, 2016, 05:08:25 pm
Sorry, I cant see a big difference

the solution from unit math !!! is
Code: Pascal  [Select][+][-]
  1. function ifthen(val:boolean;const iftrue:integer; const iffalse:integer= 0) :integer;
  2. begin
  3.   if val then result:=iftrue else result:=iffalse;
  4. end;
and my old solution is
Code: Pascal  [Select][+][-]
  1. function IfFork( Decision  :Boolean; YesInt  :Integer; NoInt  :Integer = 0 )  :Integer;
  2.   begin
  3.       if Decision then Result := YesInt else Result := NoInt;
  4.   end;

sure would be better:   IfFork( Decision  :Boolean; const YesInt  :Integer; const NoInt  :Integer = 0 )  :Integer;

and because of overloading this with a string and ...-versions  in my unit my solution is much more universal
because the ifthen solution in the math unit is limited to integer, int64 and double results

but as a german idiom says: preferences and savours are thankfully different
Title: Re: Q about new IfThen() intrinsic
Post by: BeniBela on February 04, 2016, 05:28:43 pm

Yup. There are too much such constructs in Free Pascal already. That is why I started the MSElang initiative.

No there are not enough!


Sorry, I cant see a big difference

The point is, with an intrinsic you can write

Code: [Select]
x := ifthen(obj <> nil, obj.foobar, '');


You cannot do that with the old version



Although it would be much clearer as

Code: [Select]
x := if obj <> nil then obj.foobar else '';
Title: Re: Q about new IfThen() intrinsic
Post by: skalogryz on February 04, 2016, 05:33:17 pm
Sorry, I cant see a big difference

let's have some practice, then!

1) try this code.
Code: [Select]
{$mode objfpc}
{$assertions on}
uses SysUtils;
var
  a,b : integer;
begin
  a:=4;
  b:=0;
  assert(b =0, 'the result if of division is '+IntToStr(a div b));
  writeln('b is zero!');
end.
Does it fail?

2) Now, lets change it a little bit and try again.
Code: [Select]
{$mode objfpc}
{$assertions on}
uses SysUtils;

procedure myassert(cond : boolean; const msg: string); inline;
begin
   if not cond then begin
     writeln(msg);
     halt;
   end;
end;

var
  a,b : integer;
begin
  a:=4;
  b:=0;
  myassert(b =0, 'the result if of division is '+IntToStr(a div b));
  writeln('b is zero!');
end.
Does it  fail? if yes, what's the error message?
Title: Re: Q about new IfThen() intrinsic
Post by: frakno on February 04, 2016, 05:33:58 pm
BeniBela
Quote
Code: [Select]
x := ifthen(obj <> nil, obj.foobar, '');


You cannot do that with the old version

Yeah, that's a difference i can see
Title: Re: Q about new IfThen() intrinsic
Post by: BeniBela on February 08, 2016, 11:00:23 pm
OMG, they lost their minds:  >:(

http://lists.freepascal.org/fpc-pascal/2016-February/046616.html

 >:(
Title: Re: Q about new IfThen() intrinsic
Post by: skalogryz on February 08, 2016, 11:02:30 pm
http://lists.freepascal.org/fpc-pascal/2016-February/046616.html
For the best, imho!
(Syntax) Sugar diet is not healthy.
Title: Re: Q about new IfThen() intrinsic
Post by: Zoran on February 09, 2016, 08:32:03 am
Bad news...  :(
Title: Re: Q about new IfThen() intrinsic
Post by: guest58172 on February 09, 2016, 12:30:27 pm
In the NewsGroup topic there are interesting solutions proposed to implement a Pascal-ish ternary operator (instead of the intrasic). But the problem is clear: precedence:

Code: Pascal  [Select][+][-]
  1. a :=  c > d then e else f;

Which is, I believe a problem in the grammar, since the rules have to be changed, because c > d already returns a boolean that might be assignable. In C like languages it's a bit different because expressions that evaluates to bool are surrounded with parens.

with the Q mark

Code: Pascal  [Select][+][-]
  1. a ?:=  c > d then e else f;
Code: Pascal  [Select][+][-]
  1. a ?+=  c > d then e else f;
Code: Pascal  [Select][+][-]
  1. a ?-=  c > d then e else f;

top down parsing works.

Introducing the Q mark is not a bad idea, soon or later you'll implement coalesce...
Title: Re: Q about new IfThen() intrinsic
Post by: Azarien on March 08, 2016, 12:59:59 pm
Ada 2012 introduced the following syntax:

Code: Pascal  [Select][+][-]
  1. z:=(if b then 5 else 42);

Note that the if-expression (that's what it is called) has to be parenthesized. This solves precedence problem.

This is also legal:

Code: Pascal  [Select][+][-]
  1. f:=float(if b then x else y);

which is equivalent to

Code: Pascal  [Select][+][-]
  1. f:=(if b then float(x) else float(y));

When the parentheses are required anyways, no need for additional ones:

Code: Pascal  [Select][+][-]
  1. func(if x then a else b);

I think Free Pascal could simply copy Ada syntax.
The rationale can be found here (http://www.adacore.com/uploads/technical-papers/Ada2012_Rationale_Chp2_expressions-cc.pdf).
Title: Re: Q about new IfThen() intrinsic
Post by: Azarien on March 08, 2016, 01:43:59 pm
Some other Ada 2012 examples:
Code: Pascal  [Select][+][-]
  1. P(if X > 0 then B elsif X < 0 then C else D);
  2. // we should use "else if" here
  3.  
  4. P(if X > 0 then (if Y > 0 then B else C) else D);
  5.  
  6. // special case for boolean:
  7. P(if C1 then C2);
  8. // same as
  9. P(if C1 then C2 else True);
Title: Re: Q about new IfThen() intrinsic
Post by: marcov on March 08, 2016, 03:12:30 pm
Borrowing from Ada was already discussed in the relevant threads on the maillists.
Title: Re: Q about new IfThen() intrinsic
Post by: ArtLogi on June 03, 2016, 12:41:23 am
Why ifthen() while there is Case.

Code: Pascal  [Select][+][-]
  1. Case Variable of
  2.   true: // do something
  3.   false: // do something
  4. end
  5.  
.. and if CASE command doesn't allow comparisons why ifThen() doesn't use similar clear construct as case or extend the functionality of the Case Of command. (which is really nice and clear to read compared to that brainfuck IFTHEN(=?=?=?=_?= ).. Noob is wondering.

PS. If something like ifThen() is implemented why not name it to Choose() as what I can see it do just that chose the value based on the boolean comparison(or is test in programming jargon). ??

PPS.
..or
Code: Pascal  [Select][+][-]
  1. Case Variable_A of
  2.   true: // do something
  3.   false: // do something
  4.  To variable_B
  5. end
  6.  

..or even
Code: Pascal  [Select][+][-]
  1. To variable1, variable2, variable3, variable4
  2. begin
  3.   case Variable_A of
  4.      true: // do something
  5.      false: // do something
  6.   end
  7. end
  8.  

..or even as unorthodox as
Code: Pascal  [Select][+][-]
  1. If A<>B  Then ChooseFor variable1, variable2, variable3, variable4 (*ie. list of 50 GUI elements to disable*)
  2.     True: (* actions *)
  3.     False: (* actions *)
  4.  
TinyPortal © 2005-2018