I dunno. It seems I'm in the minority, but I actually like using (o arg default). Only problem is the whole "don't use o when destructuring" thing, which is annoying. As for these options, I agree with conanite. In general, overloading either quotes or dots would be weird.
You could tweak o to be nicer to multiple parameters, though. E.g.,
(def trim (s (o where 'both) (o test whitec))
If CL's &optional came to this forum it would say: If you're going to have a new keyword like o, at least take advantage of the fact that required args can't follow optional args, and get rid of the parens.
I like how you argue this is a rare case :) My motivation is purely aesthetic, under the assumption that I'll want to make a long term commitment to a 100-year language something like arc. I'm trying to add keyword arguments to arc, and I figure I might as well revisit this decision at the same time.
Two problems with (o arg default) - you need to remember not to use 'o at the start of a destructuring list (and not get confused when you see (def handle-request ((i o ip)) ...) ), and as akkartik says it's paren-inefficient, a single keyword to delimit required/optional args would mean fewer tokens.
The first problem is easy to fix though - use a symbol that's less likely to be an arg name to identify optional args. How about '= ?
(def myfun (a b (= c (something)) ...)
it has the advantage of similarity with ruby:
def myfun a, b, c=something
disadvantage: looks silly when you don't supply a default value:
Thinking about the paired-o suggestion I made, it has an advantage over grouping single optional arguments by their own parens -- at least if you have more than 2 optional parameters :). Compare:
(a b (opt-c default-c))
(a b (o opt-c default-c))
(a b (opt-c default-c) (opt-d default-d))
(a b (o opt-c default-c opt-d default-d))
(a b (opt-c default-c) (opt-d default-d) (opt-e default-e))
(a b (o opt-c default-c opt-d default-d opt-e default-e))
It's like a 3-character &optional, just with one of the characters at the end. However, you'd need to specify nil defaults by hand (though you might let an uneven pair at the end default to nil). E.g.,
(def markdown (s (o maxurl) (o nolinks))
could, at best, become
(def markdown (s (o maxurl nil nolinks))
But paired-o also generalizes the current behavior, so we could still use the original signature.