Это работает нормально:
> lmap x {a b c} {string trim cmd.$x}
cmd.a cmd.b cmd.c
> lmap x {a b c} {list cmd.$x}
cmd.a cmd.b cmd.c
В обоих случаях string trim
и list
несколько бесполезны. Под бесполезностью я подразумеваю, что они ничего не изменяют и не добавляют к результату. Есть ли способ лучше?
Я попробовал это, но они не дали желаемого результата:
> lmap x {a b c} {return cmd.$x}
cmd.a
> lmap x {a b c} {return -code return cmd.$x}
cmd.a
> lmap x {a b c} {return -code continue cmd.$x}
cmd.a
Возвращает invalid command name "cmd.a"
Я не понимаю, почему вы воздерживаетесь от использования string trim
, в любом случае вы можете использовать lrange
set your_list {a b c}
puts [lmap x $your_list {list [lrange cmd.$x 0 end]}]
потому что [string Trim] и [lrange] в моем случае бесполезны
когда вы говорите «бесполезно», у вас проблемы с типом возвращаемого значения? что это такое ?
Я не могу последовать за тобой. Под «бесполезным» я подразумеваю, что они не добавляют/изменяют результат... даже ваш пример с lrange
не изменяет результат - так зачем же использовать lrange
?
я вижу тот же результат с puts [lmap x $your_list {list [lrange cmd.$x 0 end]}]
puts [lmap x {a b c} {return -level 0 cmd.$x}]
чего мне здесь не хватает?
Именно по этой причине был добавлен string cat
(cat
для конкатенации, по аналогии с командой Unix cat
и функцией C strcat()
). Как вы заметили, выполняемая им операция является базовой для языка Tcl, но использование ее в качестве команды упрощает lmap
.
lmap x {a b c} {string cat cmd.$x}
Этот lmap
основной скрипт компилируется в максимально эффективный байт-код.
До того, как был добавлен string cat
, официальным способом был return -level 0 cmd.$a
, что в конечном итоге было тем же самым, но на самом деле это не мнемоника! В бета-версиях 8.6 он оказался совершенно громоздким, поэтому string cat
было сделано быстро, и бета-тестеры ликовали.
Чтобы расширить то, что я имею в виду:
% tcl::unsupported::disassemble lambda {{} {
lmap x {a b c} {string cat cmd.$x}
}}
ByteCode 0x1ee2cfafbe0, refCt 1, epoch 19, interp 0x1ee2b47a820 (epoch 19)
Source "lmap x {a b c} {string cat cmd.$x}"
Cmds 2, src 34, inst 22, litObjs 2, aux 1, stkDepth 6, code/src 0.00
Proc 0x1ee2cfc5630, refCt 1, args 0, compiled locals 1
slot 0, scalar, "x"
Exception ranges 1, depth 1:
0: level 0, loop, pc 12-17, continue 19, break 20
Commands 2:
1: pc 0-20, src 0-33 2: pc 12-17, src 16-32
Command 1: "lmap x {a b c} {string cat cmd.$x}"
(0) list 0
(5) push1 0 # "a b c"
(7) foreach_start 0
[jumpOffset=-7, vars=[%v0]]
Command 2: "string cat cmd.$x..."
(12) push1 1 # "cmd."
(14) loadScalar1 %v0 # var "x"
(16) strcat 2
(18) lmap_collect
(19) foreach_step
(20) foreach_end
(21) done
% tcl::unsupported::disassemble lambda {{} {
lmap x {a b c} {expr {"cmd.$x"}}
}}
ByteCode 0x1ee2cfafde0, refCt 1, epoch 19, interp 0x1ee2b47a820 (epoch 19)
Source "lmap x {a b c} {expr {\"cmd.$x\"..."
Cmds 2, src 32, inst 23, litObjs 2, aux 1, stkDepth 6, code/src 0.00
Proc 0x1ee2cfc6430, refCt 1, args 0, compiled locals 1
slot 0, scalar, "x"
Exception ranges 1, depth 1:
0: level 0, loop, pc 12-18, continue 20, break 21
Commands 2:
1: pc 0-21, src 0-31 2: pc 12-18, src 16-30
Command 1: "lmap x {a b c} {expr {\"cmd.$x\"..."
(0) list 0
(5) push1 0 # "a b c"
(7) foreach_start 0
[jumpOffset=-8, vars=[%v0]]
Command 2: "expr {\"cmd.$x\"..."
(12) push1 1 # "cmd."
(14) loadScalar1 %v0 # var "x"
(16) strcat 2
(18) tryCvtToNumeric
(19) lmap_collect
(20) foreach_step
(21) foreach_end
(22) done
% tcl::unsupported::disassemble lambda {{} {
lmap x {a b c} {return -level 0 cmd.$x}
}}
ByteCode 0x1ee2cfb01e0, refCt 1, epoch 19, interp 0x1ee2b47a820 (epoch 19)
Source "lmap x {a b c} {return -level 0 cmd.$x}"
Cmds 2, src 39, inst 22, litObjs 2, aux 1, stkDepth 6, code/src 0.00
Proc 0x1ee2cfc68b0, refCt 1, args 0, compiled locals 1
slot 0, scalar, "x"
Exception ranges 1, depth 1:
0: level 0, loop, pc 12-17, continue 19, break 20
Commands 2:
1: pc 0-20, src 0-38 2: pc 12-17, src 16-37
Command 1: "lmap x {a b c} {return -level 0 cmd.$x}"
(0) list 0
(5) push1 0 # "a b c"
(7) foreach_start 0
[jumpOffset=-7, vars=[%v0]]
Command 2: "return -level 0 cmd.$x..."
(12) push1 1 # "cmd."
(14) loadScalar1 %v0 # var "x"
(16) strcat 2
(18) lmap_collect
(19) foreach_step
(20) foreach_end
(21) done
Как видите, байт-код с string cat
и return -level 0
один и тот же, а с expr {"..."}
есть дополнительный код операции (и, следовательно, смещение перехода отличается для его размещения).
Абсолютно все, что связано с использованием нулевого уровня для таких вещей, как возврат, повышение уровня и повышение уровня, вызывает некоторое удивление. Есть подозрение, что некоторые из них оказались там потому, что это было проще, чем предотвратить их...
я вижу тот же результат с puts [lmap x $your_list {list [lrange cmd.$x 0 end]}]
puts [lmap x {a b c} {return -level 0 cmd.$x}]
чего мне здесь не хватает?
Поместите свою версию и версию Donals lmap
в процедуру, например. proc d {} {lmap x {a b c} {string cat cmd.$x}}
и позвоните tcl::unsupported::disassemble proc d
и вы увидите, что в вашей версии намного больше шагов.
Вы также могли бы использовать expr "cmd.$x"
в теле. Коротко, но не так эффективно; выполняется дополнительный шаг, чтобы попытаться преобразовать результат в число (компилятор expr
недостаточно умен, чтобы опустить здесь этот код операции).
Я пробовал это раньше, но получил invalid bareword "cmd"
Упс, так и должно было быть expr {"cmd.$x"}
. Это немного нелепая последовательность персонажей...
Что произойдет, если вы используете
lmap x {a b c} {cmd.$x}
?