Skip to content

Switch statements [enhancement] #530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JavaGT opened this issue Apr 27, 2017 · 18 comments
Closed

Switch statements [enhancement] #530

JavaGT opened this issue Apr 27, 2017 · 18 comments

Comments

@JavaGT
Copy link

JavaGT commented Apr 27, 2017

It would be nice to have a {{#switch (VARIABLE-NAME) }} tag with complementary {{case (VALUE)}} tags. I would like to use it in a SPA rather than a number of {{if}} {{elseif}} tags.

@JavaGT JavaGT changed the title Switch statements Switch statements [enhancement] Apr 27, 2017
@Rich-Harris
Copy link
Member

I can see that being useful for e.g. routing. How exactly do you see the syntax working? This...

{{#switch route}}
  {{#case '/'}}
    <Home/>
  {{/case}}

  {{#case '/settings'}}
    <Settings/>
  {{/case}}

  {{#case '/about'}}
    <About/>
  {{/case}}
{{/switch}}

...is a bit noisier than the equivalent (which presumably it would be converted to internally):

{{#if route === '/'}}
  <Home/>
{{elseif route === '/settings'}}
  <Settings/>
{{elseif route === '/about'}}
  <About/>
{{/if}}

Perhaps there's a more compact way of expressing the same thing?

It also introduces a bit of ambiguity about fallthrough and defaults which you don't get with if. Any thoughts on how you would avoid that?

@JavaGT
Copy link
Author

JavaGT commented May 1, 2017 via email

@Rich-Harris
Copy link
Member

It's not just bikeshedding. Without a better syntax than the strawman above, it's just a less good way of doing something that already exists 😀. If it's not switch, then we veer into inventing our own language which is dangerous territory — the less people have to learn, the better.

@Conduitry
Copy link
Member

I think I'd come down in favor of no new syntax for this. It seems the main reason someone would want this would be to not have to recompute whatever it is they're comparing in each if/elseif. But then they should just be using computed properties.

@JavaGT
Copy link
Author

JavaGT commented May 1, 2017 via email

@Rich-Harris
Copy link
Member

Will close this, as I don't think there's sufficient value in adding new syntax

@jpaquim
Copy link

jpaquim commented Mar 26, 2020

@Rich-Harris any chance of revisiting this idea under the newer svelte 3 syntax?

I was just thinking about this, something like this feels natural within the context of svelte's template syntax, and has familiar semantics and syntax comparable to a JavaScript switch statement (or in any C-like language, really).

{#switch x}
  {:case 5}
    <p>{x} is 5</p>
  {:case 10}
    <p>{x} is 10</p>
  {:default}
    <p>{x} is not 5 or 10</p>
{/switch}

<!-- equivalent to something like: -->

{#if x === 10}
  <p>{x} is 10</p>
{:else if x === 5}
  <p>{x} is 5</p>
{:else}
  <p>{x} is not 5 or 10</p>
{/if}

It's not necessarily shorter, but it seems clearer and explicit about its switch/match semantics. I think not having any fall-through is a good compromise to avoid the complications with syntax mentioned in the previous responses.

@samhaaf
Copy link

samhaaf commented Feb 17, 2021

Hello,

I think quite a few people like this enhancement proposed by @jpaquim and @mjadobson. Maybe we can reopen the ticket!

TL;DR: bump

@mikeoptics
Copy link

mikeoptics commented Feb 21, 2021

@Rich-Harris any chance of revisiting this idea under the newer svelte 3 syntax?

I was just thinking about this, something like this feels natural within the context of svelte's template syntax, and has familiar semantics and syntax comparable to a JavaScript switch statement (or in any C-like language, really).

{#switch x}
  {:case 5}
    <p>{x} is 5</p>
  {:case 10}
    <p>{x} is 10</p>
  {:default}
    <p>{x} is not 5 or 10</p>
{/switch}

<!-- equivalent to something like: -->

{#if x === 10}
  <p>{x} is 10</p>
{:else if x === 5}
  <p>{x} is 5</p>
{:else}
  <p>{x} is not 5 or 10</p>
{/if}

It's not necessarily shorter, but it seems clearer and explicit about its switch/match semantics. I think not having any fall-through is a good compromise to avoid the complications with syntax mentioned in the previous responses.

I agree. I found this by looking for how to write switch statements in svelte. It is a lot more concise and readable.
I don't like the default condition at the end and would rather it be treated like how {#await} DEFAULT VALUE {:then} currently works. Using the example given above it might look like this:

{#switch x}
    <p>{x} is not 5 or 10</p>
{:case 5}
    <p>{x} is 5</p>
{:case 10}
    <p>{x} is 10</p>
{/switch}

Just providing another example below to demonstrate how much nicer looking it is:

let pets = [
    { name: "scooby", type: "dog", age: 6 },
    { name: "scrappy", type: "dog", age: 1 }, 
    { name: "lassie", type: "dog", age: 10 }, 
    { name: "franklin", type: "turtle", age: 100 }, 
]

{#each pets as { name, type, age } }
    {#switch type}
        <p>Please check with the vet what to feed {name}</p>
    {:case "dog" }
        <p>Feed {name} scooby snacks</p>
    {:case "turtle"}
        <p>Feed {name} lettuce</p>
    {/switch}
{/each}

<!-- Versus -->

{#each pets as { name, type, age } }
    {#if type="dog"}
        <p>Feed {name} scooby snacks</p>
    {:else if type="turtle"}
        <p>Feed {name} lettuce</p>
    {:else}
        <p>Please check with the vet what to feed {name}</p>
    {/if}
{/each}

Also, it turns out that performance of switch is better than that of if else. See: Here

Edit: Mentioned performance.

@bensaine
Copy link

Bump!

I'd love to see this implemented! It would be really useful as I much prefer to use a switch for many conditions for the same value. Please consider reopening this!

@blake-regalia
Copy link

For anyone who came here looking for a workaround, i came up with this simple trick that takes advantage of the fact that await in ES will return the same value for non-promises. If you have some long expression that you want to cache to a variable (in this example switch_value) to use in a series of else blocks and some value (in this example my_instance) that the expression depends on, you can use something like this:

<div>
  <!-- re-run every time `my_instance` is changed -->
  {#key my_instance}
    <!-- cache the result of the expression to `switch_value` -->
    {#await some_expression_using(my_instance, and_data) then switch_value}
      {#if 'case_1' === switch_value}
        <h4>Case 1</h4>
      {#else if 'case_2' === switch_value}
        <h4>Case 2</h4>
      {#else}
        <h4>Default Case</h4>
      {/if}
    {/await}
  {/key}
</div>

@power-f-GOD
Copy link

@Rich-Harris , please, kindly re-open. This would be a nice feature to have. I'm really not a fan of if...else if's...

Thank you.

@irishburlybear
Copy link

I just came into a need for this.

@clozach
Copy link

clozach commented May 11, 2022

Just for quick reference, in case this gets re-opened…

Here's a transcript of the syntax that @Rich-Harris recently explored at Svelte Summit. It's basically the same as what's already been suggested by @jpaquim and @mikeoptics, with added consideration for empty defaults.

Default

{#switch thing}
    something else
{:case "foo'}
    f00
{:case 'bar'}
    bar
{:case 'baz'}
    baz
{/switch}

No default

{#switch thing case 'foo' }
    f00
{: case 'bar'}
    bar
{:case 'baz'}
    baz
{/switch!

@bmitchinson
Copy link

Just for quick reference, in case this gets re-opened…

Here's a transcript of the syntax that @Rich-Harris recently explored at Svelte Summit. It's basically the same as what's already been suggested by @jpaquim and @mikeoptics, with added consideration for empty defaults.

Default

{#switch thing}
    something else
{:case "foo'}
    f00
{:case 'bar'}
    bar
{:case 'baz'}
    baz
{/switch}

No default

{#switch thing case 'foo' }
    f00
{: case 'bar'}
    bar
{:case 'baz'}
    baz
{/switch!

Thanks for the link, I hope he goes with this @Rich-Harris / @Conduitry

@ohbob
Copy link

ohbob commented Sep 8, 2022

I would totally love if this would be implemented. Looks and feels more cleaner!

@webdesireDE
Copy link

webdesireDE commented Oct 19, 2022

This approach would be even cleaner, its not necessary to have # : or / because every block can be identified

  1. switch with condition is the start
  2. no need for : in case
  3. a single switch is always the end
// Classic Switch

        {switch condition}
            <h1>Default</h1>
        {case ‚one‘}
            <h1>One</h1>
        {case ‚two‘} 
            <h1>Two</h1>
        {case ‚three‘} 
            <h1>Three</h1>
        {switch}
// Classic Switch without default 

        {switch condition case ‚one‘}
            <h1>One</h1>
        {case 'two‘} 
            <h1>Two</h1>
        {case 'three‘} 
            <h1>Three</h1>
        {switch}

To make it even more readable we can use the Liquid Approach. Its basically the same as Switch

// Liquid Like 

        {case condition}
            <h1>Default</h1>
        {when ‚one‘}
            <h1>One</h1>
        {when 'two‘} 
            <h1>Two</h1>
        {when 'three‘} 
            <h1>Three</h1>
        {case}
// Liquid Like without Default

        {case condition when ‚one‘}
            <h1>One</h1>
        {when 'two‘} 
            <h1>Two</h1>
        {when 'three‘} 
            <h1>Three</h1>
        {case}

@oodavid
Copy link

oodavid commented Dec 12, 2022

When paired with Typescript + enums or union types, I think a switch statement can add a useful warnings.

The Dart Lang has a missing_enum_constant_in_switch diagnostic message, that helps users handle all enum values.

Missing a value? Get a warning.

Here's a short video showing the dart behaviour, and a link to the dartpad code:

For example, I'd love to see Missing case clause for 'error' here:

<script lang="ts">
	export let status: 'loading' | 'ok' | 'error';
</script>

{#switch status case 'loading'}
    Loading...
{:case 'ok'}
    Awwww, yis
{/switch}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests