Attributes · Gotchas & Edge Cases · Practice Question
What Operations Cause a List to Lose Its Attribute?
Question
Besides appending out-of-order data, what other operations silently remove an attribute from a list?
Solution
n: `s# til 10
/ Arithmetic operations — always strips attribute
attr n + 1 / ` — new list, no attribute (even though still sorted)
attr n * 2 / ` — same
attr n - 0 / ` — even a no-op arithmetic strips it
/ Element replacement
n[2]: 99
attr n / ` — n lost `s after the assignment
/ Deletion
attr -1_ n / ` — dropped last element
attr 1_ n / ` — dropped first element
/ Functional assignment
@[`n; 3; :; 99] / also loses attribute
/ Grouped is the exception for item changes
g: `g# `AAPL`GOOG`AAPL
g[0]: `MSFT
attr g / `g — kept
attr -1_g / ` — but dropping items removes it
/ Table updates only replace the columns they change
t: ([] sym:`g# `AAPL`GOOG`AAPL; price: 100 200 100)
update price+1 from `t
attr t`sym / `g — sym was not changedExplanation
Any operation that produces a new list from an existing attributed list returns that new list without the attribute. kdb+ does not re-check whether the structural guarantee would still hold after the transformation — it simply discards the attribute.
This applies to:
Arithmetic — n+1, n*2, n-0, neg n, etc. Every arithmetic operation creates a new list. Even operations that are guaranteed to preserve sort order (adding a positive constant to a sorted list) still lose the attribute. kdb+ makes no exceptions.
Element replacement — n[i]: x removes s#, u# and p#, because changing a single item could break the property. Again, no check is performed. g# is the exception: kdb+ updates its index, and the attribute is kept.
Deletion — dropping items (_, or delete from a table) removes the attribute, including g#.
Table updates — update col+1 from `t replaces the col column, so col loses any attribute. Columns the update does not change keep theirs.
Why this matters:
A common production problem is a column that loses its attribute because of a modification that looks harmless — for example, trimming old rows from an in-memory table:
trade: ([] sym:`g#`AAPL`GOOG`AAPL; price:100 200 100f)
delete from `trade where price<150 / deleting rows...
attr trade`sym / ` — ...removed g# from sym
update `g#sym from `trade / so re-apply itAfter any such change, check attr and re-apply the attribute if needed.