slint icon indicating copy to clipboard operation
slint copied to clipboard

Add support for switch/match element

Open ogoffart opened this issue 2 years ago • 5 comments

Not to be confused with #241which is about expression in bindings.

It is often desirable to choose a different component base on some condition or value

if mode == 0 : Foo { ... }
if mode == 1 : Bar  { ... }

It would be nice to do

switch mode {
    case 0: Foo { }
    case 1: Bar { }
}

Maybe not switch but match, and could be combined with the for model.

for data in some_model : match data.type {
    0 : Foo { ... }
    1 : Bar { ... }
    else: Yoo { ... }  // note that this would be ambiguous if else is not a keyword     
}

We could also imagine to have an union type with data (similar to rust enums)
(or have enums with data?)

union Shape := {
     rectangle := { h: length, w: length }
     circle := { r: length }
} 

property <[Shape]> model: [ Shape.rectangle{ h: 23px, w: 43px; }, Shape.circle{ r: 4px } ];
for shape in model: match shape {
      Shape.rectangle(rect) => Rectangle { width: rect.w; height: rect.h;  }
      Shape.circle(c) => Rectangle { width: c.r; height: c.r; border-radius: c.r/2; }
}

The syntax need to be somehow defined.

ogoffart avatar Jun 02 '22 08:06 ogoffart

i would say that union/match approach could give the best result (as it is most powerful) - also simple match if there would be per-se enumerations on .slint grammar would be good - something like:

enum Shape := {
     Rect: 12,
     Circle: 13
} 

for shape in model: match data.type {
      Shape.Rect: Rectangle { width: rect.w; height: rect.h;  }
      Shape.Circle: Rectangle { width: c.r; height: c.r; border-radius: c.r/2; }
}

prnogaj avatar Jun 02 '22 08:06 prnogaj

How involved is it to build powerful (rust-like) match semantics into C++?

hunger avatar Jun 02 '22 11:06 hunger

How involved is it to build powerful (rust-like) match semantics into C++?

If the question is how to lower the proposed union into C++ for the C++ api, i guess we can lower that into a C++ variant of different type:

union Shape := {
     rectangle := { h: length, w: length }
     circle := { r: length }
} 

would become something like

struct Shape_rectangle { float h; float w; };
struct Shape_circle { float r; };
using Shape = std::variant<Shape_rectangle, Shape_circle>;

I guess we have no way around creating types and finding name for them, and using _ as a separator seems logical. Perhaps another idea would be to group them in a namespace or something.

ogoffart avatar Jun 02 '22 11:06 ogoffart

There doesn't seem to be any difference between this issue and #241, is there?

Tmpod avatar Mar 22 '24 11:03 Tmpod

#241 is for expressions (within property binding or callback handlers), while this issue is about instantiating elements

ogoffart avatar Mar 22 '24 12:03 ogoffart