s tím **nextcase** to tedy neni zadna vyhra. Jako asi chapu, ze ceckovej break je asi vic error-prone. Ale mozna by tedy uz bylo lepsi doplnit do case nejake uzitecne patterny, jako | (or) nebo .. (rozsah). IMHO by to jazyk posunulo lepsim smerem (tady k Rustu ;)))
Or je implicitní, když za case není žádný kód. Viz příklad z článku
switch (x) {
case 0:
io::printfn("%d is zero", x);
case 1:
case 3:
case 5:
case 7:
case 9:
io::printfn("%d is odd number", x);
case 2:
case 4:
case 6:
case 8:
case 10:
io::printfn("%d is even number", x);
default:
io::printfn("I don't know what to say about %d", x);
}
nextcase řeší situaci, kterou AFAIK Rust vůbec neumí. Standardně skáče na další case, ale může skočit i někam jinam (viz case 1, který skočí na case 0 nahoru):
fn void duff(int* to, int* from, int count)
{
int n = (count + 7) / 8;
switch (count % 8)
{
case 0: *to++ = *from++; nextcase;
case 7: *to++ = *from++; nextcase;
case 6: *to++ = *from++; nextcase;
case 5: *to++ = *from++; nextcase;
case 4: *to++ = *from++; nextcase;
case 3: *to++ = *from++; nextcase;
case 2: *to++ = *from++; nextcase;
case 1: *to++ = *from++; if (--n > 0) nextcase 0;
}
}30. 9. 2025, 13:20 editováno autorem komentáře
no nějaký sofistikovanější pattern matching jako má Rust, v C3 není. Tady se asi naráží na limity toho, co v jazyku typu C3 ("lepší C") očekávat a kde už je lepší se poohlédnout po těžší váze :/
V Rustu je takový skvělý pattern:
match get_status_by(args) {
Status::Success => println!("success"),
Status::Fail(e) => println!("error {}", e),
}
Strašně moc jsem to "potřeboval" v C#, který toto neumí. No, nějak jsem to přes třídu, tovární metody a vnořený enum zpáchal. A trochu jsem se k tomu Rustímu kódu přiblížil.
Chci tím říct, že ty sofistikovanější patterny, které by se nám ve switchi líbily stojí na schopnostech práce s typy, mimo jiné. Není to jen o konstrukci, ale i o tom, jak dobře kompilátor rozumí kódu.
> Chci tím říct, že ty sofistikovanější patterny, které by se nám ve switchi líbily stojí na schopnostech práce s typy, mimo jiné.
Přijde mi, že zrovna C# má pattern matching schopnější než řada funkcionálních jazyků. Skoro mi to přijde až zvrhlé - jde napsat třeba tohle:
vehicle switch
{
Car {Passengers: 0} => 2.00m + 0.50m,
Car {Passengers: 1} => 2.0m,
Car {Passengers: 2} => 2.0m - 0.50m,
Car => 2.00m - 1.0m,
Taxi {Fares: 0} => 3.50m + 1.00m,
Taxi {Fares: 1} => 3.50m,
Taxi {Fares: 2} => 3.50m - 0.50m,
Taxi => 3.50m - 1.00m,
Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m,
Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m,
Bus => 5.00m,
DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
DeliveryTruck => 10.00m,
{ } => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)),
null => throw new ArgumentNullException(nameof(vehicle))
};
Viz Tutorial: Use pattern matching to build type-driven and data-driven algorithms.
> Tady se asi naráží na limity toho, co v jazyku typu C3 ("lepší C") očekávat
Technicky by to nemusel být problém. Ale někteří autoři těchto nízkoúrovňových jazyků považují pattern matching za zbytečnost a discriminated uniony za anti-pattern z hlediska výkonu a využití paměti.
Třeba Odin má IMO lepší discriminated uniony než třeba F#. Jejich výhodou je, že typ slouží jako discriminator. Takže stačí psát:
Value :: union {
bool,
i32,
f32,
string,
}
value: Value = ...
switch v in value {
case string:
...
case bool:
...
case i32, f32:
...
case:
// Default case
// In this case, it is `nil`
}
Ale pattern matching Odin také nemá.