Arc Forumnew | comments | leaders | submitlogin
2 points by fallintothis 5176 days ago | link | parent

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))
    ...)
could instead be

  (def trim (s (o where 'both test whitec))
    ...)
Not that it's much of an issue:

  arc> (def optional (parm) (caris parm 'o))
  #<procedure: optional>
  arc> (ratio (andf alist ~dotted [some optional _]) (vals sig))
  75/494
  arc> (ratio (andf alist ~dotted [>= (count optional _) 2]) (vals sig))
  15/494
  arc> (apply max (trues (andf alist ~dotted [count optional _]) (vals sig)))
  3


2 points by akkartik 5176 days ago | link

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.

-----

3 points by conanite 5176 days ago | link

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:

  (def myfun (a b (= c) ...)

-----

2 points by fallintothis 5176 days ago | link

get rid of the parens

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.

Just food for thought.

-----

1 point by akkartik 5176 days ago | link

Yeah I'd thought of that and forgotten about it :) Thanks.

-----

1 point by akkartik 5176 days ago | link

BTW, could you tell me how common destructured args are in the arc codebase, just for comparison?

-----

3 points by fallintothis 5176 days ago | link

In def and mac parameter lists, they're pretty much never used.

  arc> (def destructuring (parm) (and (acons parm) (isnt (car parm) 'o)))
  #<procedure: destructuring>
  arc> (ratio [errsafe:some destructuring _] (vals sig))
  1/247
  arc> (keep [errsafe:some destructuring _] (vals sig))
  (((y m d)) ((y m d)))
They're most often used implicitly with let.

  $ grep "(let (" *.arc | grep -v "(let (unquote"
  app.arc:      (let (f url) afterward
  app.arc:                        (let (typ id val sho mod) it
  app.arc:  (let (nums (o label "")) (halve s letter)
  app.arc:         (let (ms ds ys) toks
  arc.arc:      (let (vars prev setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:        (let (binds val setter) (setforms place)
  arc.arc:        (let (binds val setter) (setforms place)
  arc.arc:    (let (binds val setter) (setforms place)
  arc.arc:  (let (y m d) (date s)
  arc.arc:  (let (binds val setter) (setforms place)
  html.arc:      (let ((opt val) . rest) options
  news.arc:             (let (t1 t2 t3 . rest) toks
  srv.arc:  (let (i o ip) (socket-accept s)
  srv.arc:                (let (type op args n cooks) (parseheader (rev lines))
  srv.arc:  (let (type op args) (parseurl (car lines))
  srv.arc:  (let (type url) (tokens s)
  srv.arc:    (let (base args) (tokens url #\?)
  srv.arc:      (let (kill keep) (split (rev fnids*) nharvest)

-----