-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
{#range ...} block #2968
Comments
If this feature will not impact the generated code on projects that doesn't use it, there is no impediment, IMHO. |
I'm honestly all in for a Nim, swift and others use {#range 1..5 as n} // closed: 1,2,3,4,5
{#range 1..<5 as n} // open: 1,2,3,4 It's not exactly pretty, but it's much more intuitive than Ruby's, imo. Maybe there's something else entirely? On your last point, I think even with variables (ie. runtime juggling), decrementing ranges would be fairly minimal to support. I don't know about characters... |
I'm actually the opposite, I really like the ruby |
i'd like the idea using this syntax |
I like the idea of adding support for range syntax to the |
Agree with @onkel-dirtus to use #each block.
{#each 5 as n}
{n}
{/each}
{#each 1..5 as n}
{n}
{/each} |
|
@Conduitry why can't the compiler statically determine that I don't much care if range support gets added, but always curious about the static analysis bits. |
It can't be statically analysed if a variable is used instead of a literal number ( The reason for this is that value could be provided at runtime, so the compiler will never get the chance to optimise it. I guess it would be possible to make |
@pngwn that's what is being asked for by at least some of the proposals though, a literal number. The compiler could easily identify that value and write out range code instead of array iteration code. |
I think that is why conduitry said:
I am in agreement here, limiting it to only literal numbers reduces the usefulness of range syntax. The point, to me, is to provide a more elegant syntax for iterating a set number of times without requiring an array-like. Forcing people who are using values only known at runtime to go back to |
I do not have much experience in open source community (yet), but I found this community very diverse and open, hence daring to share my opinion. I am sorry, but I am bit skeptical about this. I believe learning new language with minimal syntax is much easier and possibly less confusing. So, feeling uncomfortable having a separate block for special case of iterating. Also, afraid that there is a possibility of I don't think I am capable enough to suggest, but it would be good if there can be syntax addition for range in #each block itself. |
I'm new too, but I'm with @sahajre on this. Since it's a compiler, how about adding ranges as a syntax, eg. |
I also prefer @sahajre's |
I'll also vote for keeping an What about adding a keyword EDIT: |
I'm think keeping the Using a |
@pngwn, yes I see... but there's nothing wrong with shipping something that can be done in userspace, per se. How about The user can then use any iterator they want, including an efficient |
I don't think people should need to understand the iterator protocol to write a for loop in a svelte template. Iterators are also slow (although they have improved over time and will continue to do so). |
|
Overloading JS syntax could complicate editor support. E.g. proposed
Another option to consider is replacing dots with 'to' & |
maybe for and while loops. {#iterate-for i in range(begin,end,step)} while the default begin is 0 and step is optional. {#iterate-while (condition)} where the condition could be something connected to the dom , like |
#894 was interesting on this. From @Rich-Harris himself:
These didn't make the cut but were very clean indeed (superior to what we have currently?).
|
#each came from the popularity (at that time) of handlebars afaik, but if we stop and review the current syntax/workarounds req to implement each of the previous 3/4 looping requirements then maybe @Rich-Harris was right earlier. Surely much more natural to js developers and gives a elegant way to implement asc/desc ranges with optional steps too. Maybe time to bite the bullet and deprecate #each and replace it with #for? Would mean no more #each {length: n} kludge either : ) We managed to get rid of handlebars double curlies {{ and }} and replaced them with single { } brackets so seems like a good time to say goodbye to handlebars #each finally. |
i'm looking forward for this feature, i would prefer a modified {#each} rather than {#range} but with a ruby's flavor. maybe {#each Array in range 1 to 10 as i } ? |
Waited for some movement in this one for quite a while but it's gone very quiet so ... @Rich-Harris @Conduitry Is this dead in the water or, does switching to #for from #each seems a natural and seamless (and more js) thing to do, with new benefits and throwing off finally the old handlebars #each as legacy syntax. #each would be supported but marked as deprecated once #for was released. Also, compare the syntax of the current workarounds for #each weaknesses and then is not the argument for #for even more compelling? |
That said, this isn’t dead in the water (or it would have been closed), we just have limited bandwidth. |
@pngwn not just a keyword change, see previous comment 4 back & the wish to support ranges. Perhaps it's just too tricky as @Rich-Harris previously said in #894
|
This seems to be the place where discussions of In #894 the reasons for refusing to allow |
It seems as if the helper method approach #894 (comment), with a quick array check first, wouldn't be much of an overhead at all for components which EDIT: tagging #4289 (comment) |
Just to add to this discussion, I am currently using a similar approach, to what @antony described in his post, except I extracted it into a separate helper file for a nicer syntax. range.js export default function range(from, to) {
if (!(to > from)) throw ("first argument must be smaller then second one");
if (from !== parseInt(from) || to !== parseInt(to)) throw ("arguments must be of type integer");
if (from < 0 || to < 0) throw ("arguments must be positive");
var elements = to - from + 1;
return [...Array(elements)].map((_, i) => i += from);
} The range function accepts a positive range of numbers. To use it, you only need to import it and give it a range. <script>
import range from "range.js"
</script>
{#each range(1, 3) as i}
<p>{i}</p>
{/each} |
A slightly broader functionality of @MartinElsaesser range-function Ranges positive and negative numbers and alphabetical chars (first char only). function range(from, to, includeFrom = true) {
let isString = false
if (from !== parseInt(from) || to !== parseInt(to)) {
if (typeof from === 'string' && typeof to === 'string') {
isString = true
from = from[0].charCodeAt(0)
to = to[0].charCodeAt(0)
} else {
throw (`'range' arguments must be of type integer or string`);
}
}
const distance = Math.abs(to - from)
const length = distance + ((includeFrom || distance > 0) ? 1 : 0)
if (isString) {
if (from > to) {
return elements.map( (_, i) => String.fromCharCode(from - i) )
}
return elements.map( (_, i) => String.fromCharCode(from + i) )
} else {
if (from > to) {
return elements.map( (_, i) => from - i)
}
return elements.map( (_, i) => from + i)
}
} Examples range(1, 3) // [ 1, 2, 3 ]
range(3, 1) // [ 3, 2, 1 ]
range(-1, -3) // [ -1, -2, -3 ]
range(-3, -1) // [ -3, -2, -1 ]
range(-3, 3) // [ -3, -2, -1, 0, 1, 2, 3 ]
range(1, 1) // [ 1 ]
range(1, 1, false) // [ ]
range('a', 'c') // [ 'a', 'b', 'c' ]
range('c', 'a') // [ 'c', 'b', 'a' ] But a JS for-loop |
There is a tc39 proposal to add a range function to JavaScript. This would allow you to iterate over a range in svelte using edit: actually the syntax would have to be |
It doesn't. A few languages like CoffeeScript tried to have one range type go both ways, but then there's no way to represent empty range edge case, and resulting code gets crazy complex. |
This comment has been minimized.
This comment has been minimized.
Just weighing in to say it sounds like an ace idea, am pro the syntaxes of Main extra point - if adding support for this, please include a step parameter, so we can do increments of 5 from 0-100 |
How about {#range 1 through 5 as i}
<!-- Do stuff... -->
{/range} and {#range 1 to 5 as i}
<!-- Do stuff... -->
{/range} Optionally, the first number + the {#range 5 as i} <!-- Same as "range 0 through 5 as i" -->
<!-- Do stuff... -->
{/range} Perhaps optionally with an additional
|
Could do a similar approach to Haskell like this:
|
If we are to offer a syntax that supports the iterator protocol, I would suggest we also provide the index much like the current {#each} block does. i.e.
|
I think adding some flavor of range functions into the standard library along with some documentation would be quite natural. |
If you don't want to add a new syntax for this, I think the most reasonable route to take would be for export function* range(start: number, end: number, step: number = 1) {
for (let i = start; i <= end; i += step) {
yield i;
}
} Usage: {#each range(1, 5) as num}
{/each} Nice and simple. Currently you'd have to do {#each range(1, 5)}
{/each} Currently this isn't possible and the Svelte compiler will throw an error if you don't have the |
Just another syntax; rust // 1 2 3 4
{#range 1..5 as n}
{n}
{/range}
// 1 2 3 4 5
{#range 1..=5 as n}
{n}
{/range} Edit: a gist of all proposals so far |
Regarding stepping/incrementing, an additional, very concise syntax would be this: 0..10..100 // 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 (E.g. used by F#) |
{#range from, to}
{/range} {#range 1, 2}
{/range} <!-- optional -->
{#range from, to (index)}
{/range} {#range 1, 2 (i)}
<p>{i}</p>
{/range} |
This comment was marked as spam.
This comment was marked as spam.
so this is not moving b/c we can't coalesce around a syntax - IMHO they are all pretty much the same. |
I would simply follow #8348's idea and just allow omitting the |
Happily, now Svelte 4 has added support for doing Just let us omit the {#each range(1, 5)}
{/each} |
I agree. I'll close this in favour of #8348 |
Just letting everyone know that #14396 was just merged. You can do |
Never thought I'd say this but I think we need range blocks — we've had so many questions along the lines of 'how do I iterate n times?'.
The usual answer is one of these...
...but neither is particularly satisfying.
Anyway, we're a compiler, so we can add this for free, if we want to. The only real question is syntax. We could emulate Ruby's range operator:
{#range 5 as n}
could be shorthand for{#range 0...5 as n}
, perhaps.Complications: Ruby's operator also handles decrementing ranges (
5...1
) and strings ('a'...'z'
and'z'...'a'
), so if we were to steal that syntax then presumably we should also support those.Any thoughts?
The text was updated successfully, but these errors were encountered: