Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2022-03

case is

13 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mattias Gaertner

Hi,

I just stumbled over the new Java feature "Pattern Matching for switch". https://openjdk.java.net/jeps/420
IMO it is a misnomer, but it has some interesting ideas.

Basically for Pascal it is a case block using the "is" operator. Pseudo code:

procedure Fly(o: TObject);
begin
  case o is
    TButton: TButton(o).foo;
    TControl: TControl(o).bar;
    TComponent: TComponent(o).meh;
    nil: Msg;
  else Run;
  end;
end;

The gain versus "if o is then..." is that the compiler warns if the case statements are not sorted and can optimize the checks.

For example the above code could be converted to:

procedure Fly(o: TObject);
var
  tmp: TClass;
begin
  if onil then
  begin
    tmp:=o.ClassType;
    repeat
      if tmp=TButton then
      begin
        TButton(o).foo;
        break;
      end else if tmp=TControl then
      begin
        TControl(o).bar;
        break;
      end else if tmp=TComponent then
      begin
        TComponent(o).meh;
        break;
      end;
      tmp:=tmp.ClassParent;
      if tmp=nil then
      begin
        Run;
        break;
      end;
    until false;
  end else
    Msg;
end;

What do you think?

Mattias

Reply by email

Hairy Pixels
to Mattias Gaertner

Lol I just implemented this and made a merge request but I haven’t heard back from anyone yet so it’s just sitting there….

I basically just copied the structure used for “case of string” in that it makes if a big if-else statement.

https://gitlab.com/freepascal.org/fpc/source/-/merge_requests/147

Show quoted text 15 lines
On Mar 23, 2022, at 7:44 PM, Mattias Gaertner via fpc-devel wrote: Basically for Pascal it is a case block using the "is" operator. Pseudo code: procedure Fly(o: TObject); begin case o is TButton: TButton(o).foo; TControl: TControl(o).bar; TComponent: TComponent(o).meh; nil: Msg; else Run; end; end;

Regards,
Ryan Joseph

Reply by email

Stefan Glienke
to Mattias Gaertner: I just stumbled over the new Java feature "Pattern Matching for switch".…

JEP 420 is hardly a misnomer because it is so much more than just type checking in a switch statement - hence pattern matching. You can see in the various examples that you can combine all kinds of boolean expressions - C# has had this for quite a while and they are constantly improving it. That also means that their order is important and the compiler cannot and does not do any sanity check. Here is some nice article about the C# implementation: https://www.thomasclaudiushuber.com/2021/02/25/c-9-0-pattern-matching-in-switch-expressions/ Also I see in JEP 420 they thought of introducing variables for the different patterns to avoid having to write unnecessary boilerplate code or hardcasts - such as this:

static int coverage(Object o) {
    return switch (o) {
        case String s  -> s.length();
        case Integer i -> i;
        default -> 0;
    };
}

Ah well and using the switch statement as an expression so you get the complete package of nice and very expressive code.

Show quoted text 67 lines
On 23/03/2022 13:44 Mattias Gaertner via fpc-devel wrote: Hi, I just stumbled over the new Java feature "Pattern Matching for switch". https://openjdk.java.net/jeps/420 IMO it is a misnomer, but it has some interesting ideas. Basically for Pascal it is a case block using the "is" operator. Pseudo code: procedure Fly(o: TObject); begin case o is TButton: TButton(o).foo; TControl: TControl(o).bar; TComponent: TComponent(o).meh; nil: Msg; else Run; end; end; The gain versus "if o is then..." is that the compiler warns if the case statements are not sorted and can optimize the checks. For example the above code could be converted to: procedure Fly(o: TObject); var tmp: TClass; begin if onil then begin tmp:=o.ClassType; repeat if tmp=TButton then begin TButton(o).foo; break; end else if tmp=TControl then begin TControl(o).bar; break; end else if tmp=TComponent then begin TComponent(o).meh; break; end; tmp:=tmp.ClassParent; if tmp=nil then begin Run; break; end; until false; end else Msg; end; What do you think? Mattias _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Hairy Pixels
to Hairy Pixels: Lol I just implemented this and made a merge request but I haven’t heard back from…

I just remembered now I tried to follow the procedure to rebase the branch like they wanted but I made a big mess of things (notice how it says 400+ changes). I don’t know went wrong but you can see the changes I made in the commit history but I’m not sure how to isolate them to make a diff. Dunno, but you can still checkout the branch and try it.

Regards,
Ryan Joseph

Reply by email

Mattias Gaertner
to Hairy Pixels: Lol I just implemented this and made a merge request but I haven’t heard back from…
Show quoted text 5 lines
Lol I just implemented this and made a merge request but I haven’t heard back from anyone yet so it’s just sitting there…. I basically just copied the structure used for “case of string” in that it makes if a big if-else statement.

Did you use multiple "is" or did you check for sorted and use one loop?

"Rebase failed"

Mattias

Show quoted text 21 lines
> On Mar 23, 2022, at 7:44 PM, Mattias Gaertner via fpc-devel > wrote: > > Basically for Pascal it is a case block using the "is" operator. > Pseudo code: > > procedure Fly(o: TObject); > begin > case o is > TButton: TButton(o).foo; > TControl: TControl(o).bar; > TComponent: TComponent(o).meh; > nil: Msg; > else Run; > end; > end; Regards, Ryan Joseph

Reply by email

Hairy Pixels
to Mattias Gaertner
Show quoted text 10 lines
On Mar 23, 2022, at 10:13 PM, Mattias Gaertner via fpc-devel wrote: > Lol I just implemented this and made a merge request but I haven’t > heard back from anyone yet so it’s just sitting there…. > > I basically just copied the structure used for “case of string” in > that it makes if a big if-else statement. Did you use multiple "is" or did you check for sorted and use one loop?

No it’s just like a the case of string syntax which checks for equality with ClassType so the order does matter. Maybe it’s not exactly like what Java has then.

Yeah, see my other message. Not sure how to fix that right now but I’ll try if it actually reviewed and accepted.

Regards,
Ryan Joseph

Reply by email

Mattias Gaertner
to Hairy Pixels
Show quoted text 7 lines
[...] > Did you use multiple "is" or did you check for sorted and use one > loop? No it’s just like a the case of string syntax which checks for equality with ClassType so the order does matter. Maybe it’s not exactly like what Java has then.

Forget Java. The point is, that its "case" can be more than mere syntactic sugar. It could give a nice speed up and the compiler warns about unreachable statements.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 14 lines
On Wed, 23 Mar 2022 22:20:38 +0700 Hairy Pixels via fpc-devel wrote: > [...] > > Did you use multiple "is" or did you check for sorted and use one > > loop? > > No it’s just like a the case of string syntax which checks for > equality with ClassType so the order does matter. Maybe it’s not > exactly like what Java has then. Forget Java. The point is, that its "case" can be more than mere syntactic sugar. It could give a nice speed up and the compiler warns about unreachable statements.

I am all for merging the implementation of Ryan, but this is not my domain, so one of the compiler people needs to .

Reply by email

Hairy Pixels
to Mattias Gaertner: On Wed, 23 Mar 2022 22:20:38 +0700 Forget Java. The point is, that its "case" can be more…
Show quoted text 5 lines
On Mar 23, 2022, at 10:35 PM, Mattias Gaertner via fpc-devel wrote: Forget Java. The point is, that its "case" can be more than mere syntactic sugar. It could give a nice speed up and the compiler warns about unreachable statements.

Search for "Case statement for class introspection” and you see can the little discussion we had about a potential speed up and why it wasn’t viable so for now it’s just using a if-else statement with A.ClassType = B.ClassType comparisons. It’s just syntactic sugar at this point but it was trivial to implement and I think it’s much nicer to work with so for me that’s a total win.

Regards,
Ryan Joseph

Reply by email

Hairy Pixels
to Stefan Glienke: JEP 420 is hardly a misnomer because it is so much more than just type checking in a…
On Mar 23, 2022, at 10:09 PM, Stefan Glienke via fpc-devel wrote: JEP 420 is hardly a misnomer because it is so much more than just type checking in a switch statement - hence pattern matching. You can see in the various examples that you can combine all kinds of boolean expressions - C# has had this for quite a while and they are constantly improving it.

Yes, Swift has some of these patterns like “case something where something.name == “John”:” but that’s another feature altogether.I see the reason for this and it’s interesting but I don’t think there’s any chance they would allow this in FPC so I skipped over it.

Regards,
Ryan Joseph

Reply by email

Hairy Pixels
to Hairy Pixels: Search for "Case statement for class introspection” and you see can the little…
On Mar 24, 2022, at 8:14 AM, Hairy Pixels wrote: Search for "Case statement for class introspection” and you see can the little discussion we had about a potential speed up and why it wasn’t viable so for now it’s just using a if-else statement with A.ClassType = B.ClassType comparisons. It’s just syntactic sugar at this point but it was trivial to implement and I think it’s much nicer to work with so for me that’s a total win.

I just realized one thing worth changing. So this is how I implemented it, essentially it’s a case-of-ClassType, which means the compiler now has: case of ordinal, case of string and case of classType.

c := TInterfacedObject.Create;
  case c of
    TObject:            result := 1;
    TInterfacedObject:  result := 2;
    TAggregatedObject:  result := 3;
    otherwise           result := 4;
  end;

But because I did an implicit “c.ClassType” it wouldn’t be possible to use “nil” as a case. Maybe not a big deal because you can capture nil in “otherwise” but it’s something to consider.

Regards,
Ryan Joseph

Reply by email

Hairy Pixels
to Michael Van Canneyt: I am all for merging the implementation of Ryan, but this is not my domain, so one of the…
Show quoted text 5 lines
On Mar 24, 2022, at 7:21 AM, Michael Van Canneyt via fpc-devel wrote: I am all for merging the implementation of Ryan, but this is not my domain, so one of the compiler people needs to look at it.

FPC badly needs another reviewer or someone with authority otherwise. I’ve been waiting for Sven to get cleared up with the closures but this is taking months and years and in the mean time the “implicit function specialization” has been sitting there for a year already (started it in 2019) and now we have the Extended RTTI which is in the pipeline (can they be merged soon?).

Given that this could take well over a year to get reviewed and merged but at least Sven did approve of the idea. If a project has these kinds of delays in management it’s probably time to reconsider some things, no?

Regards,
Ryan Joseph

Reply by email

Florian Klämpfl
to Hairy Pixels
Show quoted text 13 lines
Am 24.03.2022 um 02:40 schrieb Hairy Pixels via fpc-devel : > On Mar 24, 2022, at 7:21 AM, Michael Van Canneyt via fpc-devel wrote: > > I am all for merging the implementation of Ryan, but this is not my domain, > so one of the compiler people needs to look at it. > FPC badly needs another reviewer or someone with authority otherwise. I’ve been waiting for Sven to get cleared up with the closures but this is taking months and years and in the mean time the “implicit function specialization” has been sitting there for a year already (started it in 2019) and now we have the Extended RTTI which is in the pipeline (can they be merged soon?). Given that this could take well over a year to get reviewed and merged but at least Sven did approve of the idea. If a project has these kinds of delays in management it’s probably time to reconsider some things, no?

You can always create a fork and merge what you think is good. If people like it, they will use it.

Reply by email