Skip to content
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

Make #each work with ES6 Maps and Sets #4405

Closed
swyxio opened this issue Feb 12, 2020 · 6 comments
Closed

Make #each work with ES6 Maps and Sets #4405

swyxio opened this issue Feb 12, 2020 · 6 comments

Comments

@swyxio
Copy link
Contributor

swyxio commented Feb 12, 2020

Is your feature request related to a problem? Please describe.

this works

<script>
	var temps = new Map()
	temps.set('foo', 123)
	temps.set('bar', 234)
	var temps2 = new Set([1,2,3])
</script>

{#each [...temps.keys()] as temp}
	<div>
		{temp}
	</div>
{/each}
{#each [...temps2.keys()] as temp}
	<div>
		{temp}
	</div>
{/each}

this doesnt work

<script>
	var temps = new Map()
	temps.set('foo', 123)
	temps.set('bar', 234)
	var temps2 = new Set([1,2,3])
</script>

{#each temps.keys() as temp}
	<div>
		{temp}
	</div>
{/each}
{#each temps2.keys() as temp}
	<div>
		{temp}
	</div>
{/each}

REPL: https://svelte.dev/repl/06669274098b42b7b5f51a57603cd7d8?version=3.18.2

Describe the solution you'd like

#each should "just work" with iterables

Describe alternatives you've considered
do nothing

How important is this feature to you?
medium importance, i feel like svelte should embrace all new js features

@swyxio
Copy link
Contributor Author

swyxio commented Feb 12, 2020

i'm happy to work on a PR if you feel this is worth doing and also i'm not missing somethign ovious

@Conduitry
Copy link
Member

Duplicate of #3225/#4289/probably others. If this is proposing an implicit Array.from(), I'm not to excited about that. If this is proposing something more efficient than that, I'd be really interested to hear it, but I do really doubt we could do better, especially with keyed eaches.

@swyxio
Copy link
Contributor Author

swyxio commented Feb 13, 2020

welp, #894 pretty much answered it. sorry i didnt see these in my cursory search (which i did do but i admit i didnt look very hard)

@swyxio swyxio closed this as completed Feb 13, 2020
@swyxio
Copy link
Contributor Author

swyxio commented Feb 13, 2020

a dev-time instruction telling users to manually spread when they try giving an interable would be very nice tho, if you are interested in a dev-only warning

@brandonmcconnell
Copy link
Contributor

@sw-yx & @Conduitry

I took some time to look over the issues you both linked to, and I still think this issue holds some legitimate ground, as Sets and Maps are both considered array-like and can be handled by for…of loops, very similarly (and arguably more performant) than the way the {#each ...} block is currently set up to work with arrays.

Based on @Rich-Harris's comment on #894, the {#each} block uses a for loop in the background:

[paraphrased] If you take some code like the default each block example, Svelte iterates over the array using a for-loop.

If that is true, then why shouldn't it also work for maps and sets. Both are iterable as array-like objects without needing to spread their values to arrays. Both natively support the for…of loops, which works more closely to an actual each block anyway. It should be easy enough to convert the for-loop Rich mentioned to a for…of loop.

I created a demo at this REPL.

** NOTE: This REPL only exists to demonstrate that Maps and Sets can be processed by for…of loops and can even support an "index" value as the {#each} block currently does ({#each data as datum, index}). In the REPL, I do pass the data back to the top-level component as an array only because that is currently what is required to loop through and render the data to the preview. The main focus of the REPL is the for…of loop itself and how it allows for processing of all Arrays, Sets, and Maps alike.

Here is what that looks like:

<script>
  export let arrayLike = []; // can be array, set, or map
  let i = 0;
  for (const item of arrayLike) {
    // do something with `item` here
    i += 1;
  }
</script>

I would be happy to work on a PR for this, maybe even in collaboration with @sw-yx (if you're still up for it, Shawn) 👋🏼

@swyxio
Copy link
Contributor Author

swyxio commented May 28, 2022

only if the maintainers want it, which it seems like they dont

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

3 participants