elvish icon indicating copy to clipboard operation
elvish copied to clipboard

Map Iteration

Open iandol opened this issue 2 years ago • 2 comments

In Ruby at least, maps can be iterated over using each {|key, value| ..} — this is very easy and intuitive. I thought if one value was specified it would be the key, and two would be key and value, the magic happening in each:

put &a=1 &b=2 | each {|k| echo $k }
put &a=1 &b=2 | each {|k v| echo $k"="$v }

But there are more types of syntax for iteration. I was searching on previous proposals for iteration of maps and found #1243 which is supposed to be about strings but thanks to @krader1961 expanded to discuss iterating maps. @hanche thought of more options to iterate over maps:

@krader1961 You're doing great at being devil's advocate! At the opposite end of the available options, I've been thinking a bit about maps and how to iterate them. I was wondering above whether iterating a map should yield just the keys, or key-value pairs. So I had an idea: Why not both? So here we go, then:

Assuming $map holds a map, we could let $@map expand to the keys, and (wait for it) $@@map expand to key-value pairs.

What about all? Well, since we already have keys to extract the keys, we could let all $map produce key-value maps. I know, that makes for a bit of inconsistency, since ideally, (all $map) should be equivalent to $@map. But, I am brainstorming here. Maybe someone can think of a better way.

And finally, we could extend the for syntax, allowing both for key $map { … } and for key value $map { … }. The latter, being syntactically different, can't be confused with the single-variable version of for.

A totally different option would be to let iteration of a map always return key-value pairs, and then using destructuring, we could write the above examples as for [key _] $map { … } and for [key value] $map { … }. This allows for greater consistency, perhaps. Then $@map would return key-value pairs, as would all $map. Come to think of it, then we could get the keys by $@map[0].

Originally posted by @hanche in https://github.com/elves/elvish/issues/1243#issuecomment-780381048

iandol avatar Jan 23 '23 16:01 iandol

Destructuring is a generally useful feature, so I prefer using it for iterating maps. Something like:

var m = [&k=v &k2=v2]
pairs $m
# ▶ [k v]
# ▶ [k2 v2]
pairs $m | each {|[k v]| ... }
# ...

It's slightly awkward to use in a for loop:

for [k v] [(pairs $m)] { ... }

But maybe for can special-case maps:

for [k v] $m { ... }

xiaq avatar Dec 31 '24 17:12 xiaq

Pattern matching / destructuring in general has a tracking issue #217. For map iteration specifically we need:

  • A pairs command that outputs [k v] pairs of a map
  • Destructuring a list with a known number of elements
  • Maybe: special-casing maps in the for loop

xiaq avatar Dec 31 '24 17:12 xiaq