Perhaps we need to make the is parameterizable as well in the general case. Hmm, this could be a generalization of my firsttime (http://arclanguage.org/item?id=12889)
(firsttime user!loggedin
(prn *welcome-message*))
(updating (uvar u last-login) (date)
:body
(++ karma.u))
; track largest value seen so far
(ret max 0
(each elem '(1 3 2 6 5)
(updating max :iff > elem
(prn "max now: " max))))
max now: 1
max now: 3
max now: 6
6
Hmm, I might get rid of firsttime altogether. Is updating the right name for this macro?
You're evaluating the subexpressions of 'place twice, which isn't necessary thanks to 'setforms. Also, I like to have macros macro-expand and evaluate their parameters from left to right if I can, just for similarity with 'do. (I still try to evaluate only as much as I need to though.) To accomplish these things, I'd go with this (untested) implementation instead:
In the meantime, for the purposes of dates, I'd at least use 'iso instead of 'is. You're probably not going to get the same (date) list as one you have from earlier today. Even if (date) itself made that guarantee, you've potentially persisted and un-persisted the user data today.
In fact, since you've already made 'iso extensible, I'd use it as the default instead of 'is.
Saying (do.foo ...) instead of (foo ...) just makes it so that 'foo isn't in function position. That means the local variable 'foo will always be used instead of some macro named 'foo that happened to be defined in another library.
The ssyntaxes .foo and !foo are short for get.foo and get!foo. Also, a:b ssyntax is handled before a.b ssyntax, giving the : lower precedence.
That means (.new-val:do.setter-getter) compiles as though it's ((get new-val) ((do setter-getter))), which makes it a roundabout way to accomplish ((do.setter-getter) new-val) with one less pair of parentheses, one less character, or (by my count) one less token.
It's really sort of silly in this case, since you save on so little while rearranging so much. In its favor, he (.a:b ...) idiom makes a bit more sense when it's a field/element access like (!width:get-rect ...) or (!2:setforms ...). It's especially helpful when it's part of a big chain of composed forms like (.a:b:.c:.d:e ...).
In my own code, including Lathe, I define this:
(def call (x . args)
(apply x args))
Then the code is just call.setter-getter.new-val, giving a savings of two characters, two pairs of parentheses, or (by my count) four tokens, all without causing the expressions to be rearranged.
Saying (do.foo ...) instead of (foo ...) just makes it so that 'foo isn't in function position. That means the local variable 'foo will always be used instead of some macro named 'foo that happened to be defined in another library.
Not in Arc. The best you get is (.g:.d:.c:a "b"), I think. You can shove "b" into ssyntax with string!b, but you need to use it as an argument somehow, and any ssyntax containing .string!b will pass the 'string function itself as an argument instead of calling it first.
Of course, if "b" were a symbol instead of a string, it would just be "a!b.c.d.g".
In Penknife, the answer to your question is actually yes: It's "q.b'a.c.d.g", where q is the string-quoting operator and ' is an operator that acts like a reverse a.b. It's easy to stump Penknife too, but I'm hoping to make a full thread about Penknife's take on infix operators in a couple of days or so.
arc> (= test (obj "a" "my a val" "b" "my b val"))
#hash(("a" . "my a val") ("b" . "my b val"))
arc> test%a
"my a val"
[edit: actually, it would be nicer to have the percent symbol represent the spaces in the string and have some other symbol signify string handling, but I never got around to it + my scheme foo is lacking :)]