How this line works

Can someone explain me how the following line works line works:

p: raze(,‘/)’ [rs]

Here the rs is N * N dimensional list and each cell inside it is a M * M size string list (i.e each cell is a list of M strings of length M)

Output p is NM * NM dimensional string list (i.e NM strings of length NM)

As an example, consider
rs: 2 2# enlist 2 2# “a”
 then by doing p: raze(,‘/)’ [rs]

we will get
aaaa

aaaa

aaaa

aaaa

Can someone dissect the line and help me understand

TIA.
 - Rohith

P.S

The code snippet from this excellent repo https://github.com/adotsch/aoc/blob/master/2020/day20.q  which had concise and efficient Advent of code 2020 solutions. I found it when I was looking around to compare my solutions. I ve been trying to learn from his solutions but got stuck at that part.

It will be easier to see it this way

q)rs:2 2 2 2#16#.Q.a

q)rs
“ab” “cd” “ef” “gh”

“ij” “kl” “mn” “op"

Now lets dissect (,’/)’  one by one

Rightmost each(‘) is just iterating an top level lists in rs, so we can ignore that for the time being and directly look at rs[0]

q)(,'/)rs 0

“abef”

“cdgh"

this is basically a combination of dyadic over with each-both join (,')

kind of same as for a two element rs[0] — joining side ways

q)rs[0;0] ,’ rs[0;1]

“abef”

“cdgh”

q)raze each flip rs 0

“abef”

“cdgh"

Now you do the same on all top level lists of rs using each (‘)

q)(,‘/)’[rs]

“abef” “cdgh”

“ijmn” “klop"

then reduce the top dimension with raze

q)raze(,‘/)’[rs]

“abef”

“cdgh”

“ijmn”

“klop"

You can condense it further by removing unnecessary brackets

q)raze(,‘/’)rs

“abef”

“cdgh”

“ijmn”

“klop"

-Ajay

Thank you, Ajay. The explanation is easy to follow!