长度为一的 tcl 列表和标量之间的区别?
我有一个从“数据库”读取“字段”的 ac 函数(dbread)。这些字段中的大多数都是单值的;但有时它们是多值的。所以我的 C 代码说
if valcount == 1
return string
else
make list
foreach item in vals
append to list
return list
因为我认为大多数时候人们想要一个标量。
然而这样做会导致一些奇怪的解析错误。具体来说,如果我想添加一个值,
set l [dbread x] # get current c value
lappend l "extra value" # add a value
dbwrite x {*}$l # set it back to db
如果 x 具有单个值并且该值包含空格,则 lappend 解析错误。我得到一个包含 3 个项目而不是 2 个项目的列表。我发现这是因为它传递了一些不是列表的内容,并将其解析为列表并看到 2 个项目。
set l "foo bar"
lappend l "next val" # string l is parsed into list -> [list foo bar]
所以我最终得到 [list foo bar {next val}]
无论如何,解决方案是让 dbread 始终返回一个列表 - 即使只有一项。我的问题是 - 这有什么缺点吗?对于 90% 的情况,人们期望标量,是否存在潜伏的惊喜?
另一种选择是做我自己的 lappend 来检查 llength == 1 和特殊情况
I have a c function (dbread) that reads 'fields' from a 'database'. Most of those fields are single valued; but sometimes they are multi-valued. So I had c code that said
if valcount == 1
return string
else
make list
foreach item in vals
append to list
return list
Because i thought most of the time people want a scalar.
However doing this leads to some odd parsing errors. Specifically if I want to add a value
set l [dbread x] # get current c value
lappend l "extra value" # add a value
dbwrite x {*}$l # set it back to db
If x has single value and that value contains spaces the lappend parses wrong. I get a list with 3 items not 2. I see that this is because it is passed something that is not a list and it parses it to a list and sees 2 items.
set l "foo bar"
lappend l "next val" # string l is parsed into list -> [list foo bar]
so I end up with [list foo bar {next val}]
Anyway, the solution is to make dbread always return a list - even if there is only one item. My question is - is there any downside to this? Are there surprises lurking for the 90% case where people would expect a scalar
The alternative would be to do my own lappend that checks for llength == 1 and special cases it
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为拥有一个总是返回结果列表的 API 会更简洁,无论是一个结果还是多个结果。这样就不需要特殊的外壳。
没有坏处,只有好处。
想一想,如果您不再返回单个标量,并且将来会返回一个单个值,而该值恰好是一个带有空格的字符串,该怎么办?如果您没有构造该单个值的列表,您会将其视为两个值(因为 Tcl 会将字符串闪烁到两个事物的列表中)。通过始终构建返回值列表,所有使用 API 的代码都将正确处理此问题。
仅仅因为 Tcl 没有严格的类型并不意味着在不同时间返回不同类型是好的风格。
I think it's cleaner to have an API which always returns a list of results, be it one result or many. Then there's no special casing needed.
No downside, only upside.
Think about it, what if you move away from returning a single scalar and have a case in the future where you're returning a single value that happens to be a string with a space in it. If you didn't construct a list of that single value, you'd treat it as two values (because Tcl would shimmer the string into a list of two things). By always constructing a list of return values, all the code using your API will handle this correctly.
Just because Tcl doesn't have strict typing doesn't mean it's good style to return different types at different times.
我过去采取的方法之一(当每行的数据可能包含空值或空字符串时)是使用列表列表的列表:
它看起来很复杂,但如果你处理实际的数据项,它实际上并不复杂作为不透明的数据结构并添加访问器来使用它:
诚然,比您正在寻找的复杂得多,但我认为值得一提。
One of the approaches I have taken in the past (when the data for each row could contain nulls or empty strings), was to use a list of lists of list:
It looks complicated, but it's really not if you treat the actual data items as an opaque data structure and add accessors to use it:
Admittedly, far more complicated than you're looking for, but I thought it worth mentioning.