How to refer to a name in a loop?

Hi !
I’m trying to create a loop in cetz.
I want to refer to contents in order to place some arrows.
Here is my code without loop :

content((0,0),[$u_0$],name:"u0")
content((1,0),[$u_1$],name:"u1")
content((2,0),[$u_2$],name:"u2")
content((3,0),[$u_3$],name:"u3")
content((4,0),[$...$],name:"u4")

bezier("u0.north-east","u1.north-west", (0.5,.6),mark:(end:"straight",length:0.08cm))
bezier("u1.north-east","u2.north-west", (1.5,.6),mark:(end:"straight",length:0.08cm))
bezier("u2.north-east","u3.north-west", (2.5,.6),mark:(end:"straight",length:0.08cm))
bezier("u3.north-east","u4.north-west", (3.5,.6),mark:(end:"straight",length:0.08cm))

content((0.5,.5),$+ r$)
content((1.5,.5),$+ r$)
content((2.5,.5),$+ r$)
content((3.5,.5),$+ r$)

Here’s what I tried :

for i in range(4) {
  content((i,0),[$u_#i$],name:"u"+#i)
  bezier(("u.i.north-east", 0.5, "u.(i+1).north-west"),mark:(end:"straight",length:0.08cm))
  
}

It doesn’t work that way.
I want to create names based on the loop and also to refer to those names in the loop.
I don’t know if I’m clear :confused:

Can someone help me ?
Thank you :slight_smile:

Hi!

Without being able to execute your code, because you don’t provide a minimal working example, I’m guessing that your syntax and formatting in the loop is not quite right because you have to make sure the i is interpreted as a string:

#for i in range(4) {
  content((i,0),[$u_#i$],name:"u"+str(i))
  bezier(("u."+str(i)+".north-east", 0.5, "u."+str(i+1)+".north-west"),mark:(end:"straight",length:0.08cm))

Edit:

You can’t access u.(i+1) inside the same loop iteration — that node won’t exist yet. You’ll either need two separate loops or restructure the commands so that the necessary nodes are already defined when referenced.

1 Like

Thank you very much.

Indeed, I understood myself that it won’t be able to access the second item because it doesn’t exist yet.
But my main question was about the “u”+str(i), so, in some way, I had the answer I came looking for.

For the context, sorry, here is my whole code :

#import "@preview/cetz:0.3.2"

#cetz.canvas(length:e,{
  import cetz.draw: *
  scale(1)

let a = 7

for i in range(a) {
  content((i,0),[$u_#i$],name:("u"+str(i)))
  }

for i in range(a){
  line("u"+str(i),"u"+str(i+1),mark:(end:"straight",length:0.08cm))
}

})

As you can see, I did a second loop, where I’m referring to names created in the first one. But it doesn’t work :confused:

The following works:

#import "@preview/cetz:0.3.4"

#cetz.canvas({
  import cetz.draw: *

  let a = 7
  
  for i in range(a) {
    content((i,0),[$u_#i$],name:("u"+str(i)))
  }
  
  for i in range(a - 1){
    line("u"+str(i),"u"+str(i+1),mark:(end:"straight",length:0.08cm))
  }
})

In the second loop, you tried to access element “u” + str(a + 1), which does not exist for index 6 (7).

1 Like