하, 이거 때문에 계속 헛돌고 있어요. Arch에서 Tcl 9.0, tclsh main.tcl로 돌리고 있고, 고객사 하드웨어 자재 사이트용 작은 주문 리포트예요.
config.tcl에 규칙이 하나(total >= 200)만 있을 땐 다 잘 돌았어요. 그러다 고객 메모가 있는 주문도 표시되게 두 번째 규칙을 추가했어요:
set ::flag_rules {
{total >= 200}
{note ne {}}
}
이제 실행하다가 중간에 invalid command name "Dana"로 죽어요. 트레이스는 rule_match의 expr 줄을 가리켜요:
proc rule_match {row rule} {
lassign $rule field op value
set have [dict get $row $field]
return [expr "\"$have\" $op \"$value\""]
}
"Dana"는 제 코드 어디에도 명령으로 없어요. 데이터에 있어요. 금액이 큰 주문 중 하나의 메모가 orders.tsv에 이렇게 들어 있어요:
1003 Petrakis Plumbing 1250.75 call [Dana] before shipping
다른 메모(예: "leave at side door")는 문제없이 통과해요. 크래시 직전에 row dict를 출력해 봤는데 완전히 정상으로 보여요. 탭도 제대로 나뉘었고, 필드 네 개 다 제자리에 있고, 메모도 그대로예요. 그래서 한 시간째 load_orders만 뒤지고 있었어요. 고객사 export에 이상한 인코딩 문제나 stray byte가 있는 줄 알았거든요. Neovim에서 :set list로 확인했는데 탭은 탭으로 보여요. (참고로 메모가 빈 행에는 끝에 탭이 붙어 있는데 1005번만 안 붙어 있는 건 왜일까요? 이건 다른 문제니까 다음에 볼게요.)
도저히 모르겠는 건 dict 안에 있는 문자열이 어떻게 명령 호출이 되느냐예요. 아무것도 eval하지 않는데요. 왜 이 행만 그럴까요?
영어에서 번역·원문 보기Okay, this one has me chasing my tail. Tcl 9.0 on Arch, tclsh main.tcl, small order report for a client's hardware-supply site.
I had one rule in config.tcl (total >= 200) and everything was happy. Then I added a second rule so orders with a customer note get flagged too:
set ::flag_rules {
{total >= 200}
{note ne {}}
}
Now the run dies partway through with invalid command name "Dana". The trace points at the expr line in rule_match:
proc rule_match {row rule} {
lassign $rule field op value
set have [dict get $row $field]
return [expr "\"$have\" $op \"$value\""]
}
"Dana" isn't a command anywhere in my code. It's in the data. One of the bigger orders has this note in orders.tsv:
1003 Petrakis Plumbing 1250.75 call [Dana] before shipping
Other notes (like "leave at side door") go through fine. I printed the row dict right before the crash and it looks totally normal. Tabs split right, all four fields in place, note intact. So I've been poking at load_orders for an hour, convinced the client's export has some weird encoding thing or a stray byte. Checked in Neovim with :set list, tabs look like tabs. (Side note: why does their export have a trailing tab on the empty-note rows but not on 1005? Different problem, different day.)
What I can't see is how a string sitting in a dict becomes a command call. Nothing evals it. Why only this row?