Problem with for loop with list if list is empty

I've found a problem with the for loop block. Technically it's not a bug I guess, but it is annoying. If you have it like this:

[scratchblocks] for ((i) :: control) = (1) to ([length v] of (list) :: list) { ... } @loopArrow :: control [/scratchblocks]

if the list is empty, it will evaluate to this:

[scratchblocks] for ((i) :: control) = (1) to (0) { ... } @loopArrow :: control [/scratchblocks]

This makes the for loop go backwards from 1 to 0, and calling the inner blocks with the variable (i) as 1 and then 0. Which is a problem if your list is empty, because there are no items and therefore if you were to index an item in the loop, it would throw an error. I'm not sure if you developers are aware of this.

Of course there's an easy fix by wrapping it in an "if list is not empty", but I believe this shouldn't happen in the first place, since in other programming languages if you do the equivalent of this, it would work as it should if the list is empty (because arrays/lists usually start at 0).

By the way, I need to use this specific for loop block for the list to keep track of the index.

We're definitely aware of it. The thing is, sometimes people do want a FOR loop to count backward:
Sans titre script pic
So I think your use of "as it should" is unjustified, especially since we have FOR EACH ITEM to handle most of the cases of iterating through a list.

It wouldn't kill me if we replaced the word "to" in the FOR block with a pulldown with choices "to" and "up to." But I'm predicting that Jens won't go for it, since you can do it with blocks in the Iteration and Composition library.

It would make me very happy if the FOR EACH block had a right arrowhead after ITEM that would expand it to include INDEX, but I've raised that with Jens and he's not enthusiastic about the idea. That would leave very few cases, if any, in whichi FOR EACH wouldn't handle your list traversal needs.

For the specific case "for 1 to length of a list" you can use:

image

nothing happen with an empty list
(enable javascript)

Why? This block is in the List Utilities library and doesn't need JS.

because the "linked?" block inside...

Oh gosh is that still there? Now that we have FOR EACH as a primitive, which works efficiently for both linked lists and dynamic arrays, it should be replaced with


I'll see to that...

image
image
So like this?

How come?

I'm thinking the one with INDEX would have only a leftarrow. Having a LIST upvar seems kind of redundant given that the list input is right there next to it. But I wouldn't insist on that; for consistency with MAP maybe it should allow LIST too.

I wish I knew. It seems totally reasonable to me, especially for people who are accustomed to the corresponding MAP feature.

By that analogy MAP itself wouldn't have a LIST upvar. The thing that is probably keeping it from being removed is that it's more efficient; the list is only evaluated once.

Nah, what keeps it there is that that's a JS feature. :~) The really right thing would be to provide the portion of the list from this item to the end as the third input (one of those things figured out half a century ago in Lisp...).

So the CDR of the (linked) list the previous item is in?

Yes, exactly.

So I got it right first time. (Not that there were more than that, though.)

Had a similar problem with using "for i" to "write" each item in a list. Two words were written next to each other, no space, with the blank element ignored.

Blank element in a list? WRITE doesn't add spaces unless it's given spaces as an input.