Arc Forumnew | comments | leaders | submitlogin
A bug with templates
3 points by akkartik 1770 days ago | 5 comments
Templates can't handle nil fields unless nil is the default value:

  (deftem foo field1 'default)
  (w/outfile f "x"
    (write-table (inst 'foo 'field1 nil) f)) ; field1 = nil
  (temload 'foo "x") ; field1 is set to 'default
(Thanks markkat for helping find this.)


2 points by rocketnia 1770 days ago | link

Sounds like a "feature" of templates to me, just like a nil value in a table deleting its key is a "feature."

...In fact, isn't it just the same thing? I'm not so familiar with templates, but you're using 'write-table, which will presumably take a table, which will supposedly omit any nil fields. When you read it again, the field won't be there, and what purpose is there to having a default if not to use it now?

-----

1 point by akkartik 1770 days ago | link

I won't quibble about names :) Let's just agree that templates initializing unspecified values to defaults interacts poorly with tables deleting nil values.

-----

1 point by rocketnia 1769 days ago | link

Yeah, I guess that's something we can agree on. No use having a serialization mechanism that thinks the stored version of the value is just a suggestion. :)

Until now, I was thinking this was potentially a positive (albeit an inconsistent positive) since it was a convenience to anyone who wanted to manually edit pickled values, as might happen with a configuration file or something. That doesn't seem nearly as crucial a feature as serialization, and from the looks of your 'temstore utility, it might even still be possible.

-----

2 points by akkartik 1769 days ago | link

Fixed: http://github.com/nex3/arc/commit/5edcb35d4b

Instead of using write-table directly, use temstore:

  > (deftem foo field1 'default)
  > (temstore 'foo (inst 'foo 'field1 nil) "x") ; field1 = nil
  > ((temload 'foo "x") 'field1)
  nil

-----

2 points by akkartik 1768 days ago | link

Templates are now first-class tagged types: http://github.com/nex3/arc/commit/d2a1f507e0

I've made two incompatible changes, however.

a) Default values are not inlined during initialization. Before:

  > (inst 'foo)
  #hash((field1 . default))
After:

  > (inst 'foo)
  (tagged tem (foo #hash() ...))
Non-existent fields are looked up from the template at read time. This is useful if you ever want to change the default. Say you decide to change the default value for showdead in HN. If you updated the template today it would only update for new users. You could go through and set everybody's showdead, but that seems invasive. After my changes existing users will pick up the new default, but if somebody tried setting showdead in the past and explicitly reset it to the default -- then they get to keep their setting.

b) Reading from file now includes all fields rather than just the ones included in the template. Does this seem reasonable? I think the reasoning for dropping unknown fields was so you could upgrade or rollback the template and it would work with existing data. But if you delete a field it doesn't do any harm if it's set, right?

inst has always permitted unknown fields, so this way things seem more consistent.

-----