Arc Forumnew | comments | leaders | submitlogin
Yet another []-Syntax Proposal
2 points by mnemonicsloth 6162 days ago | 6 comments
A few points about proposed syntax for extra [] args:

1. First-time users of the language have to be told about _ . It is a necessary onion.

2. Having two arguments for [...] is about as big a win as having just one. Unary and binary fn's are really common, but higher arities aren't. Also, with a two-argument [..], you can do compositions and such in a much more straightforward and readable way.

3. If you're going to have a systematic naming convention -- $1 $2 $3 -- you wind up with either CL-ish duplication of the (fn) form's role, or some kind of arbitrary cutoff where $(n-1) is OK but $n is verboten.

So I propose the following: [foo _] => (fn (_) (foo _))

   [_ 'bar []] => (fn (_ []) (_ 'bar []))
This is good because:

1. Currently [] returns the always-nil function, which you also get with [nil]. Waste!

2. Good compression -- no more characters spent on funargs.

3. Don't have to spend any more characters, and no ugly doubling like __.

3. [] looks like it means "nonce". See the second sexpr in http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-15.html#node_sec_13.1

4. Having [..] work for just {0, 1, 2} arguments isn't much more arbitrary than having it work for just {0, 1}, and your cognitive load is reduced because you can choose between fn and [..] autonomically.

I'm more than half inclined to think this will turn out to be a stupid idea, but it also feels a little bit elegant (we need one unique symbol, we have one redundancy, and we are prevented from going any further so the syntax stays simple). I don't know enough about the PLT reader to implement this myself and don't have time to learn, so I've got to rely on you folks to find out. What do you think?



2 points by sjs 6162 days ago | link

I think it's important to distinguish between what's read and what's executed. The reader translates [] into (make-br-fn '()), which expands to (fn (_) ()). I am totally stumped as to what (fn (_ (fn (_) nil)) (_ 'bar (fn (_) nil))) could or should mean. It seems as if you are thinking about [] as a symbol in [_ 'bar []] => (fn (_ []) (_ 'bar [])), but that is confusing. When thinking about [...] on this level we should be thinking in terms of the actual sexps evaluated. Translating [] to (fn (_) nil) outside [...] and to something else inside them is a road to madness and some serious reader hacking.

[] never expands to a function of zero arguments. ([]) is an error, too few arguments.

[nil] is not the always nil function. I had the same misconception at first, that the ... in [...] is the body of the fn, but (...) is the real body. The [] are simply replaced with (), so the body is always a function application and never an atom, save for the special case of [] -> () -> nil. [] and [idfn nil] are 2 always-nil functions, but the fact that [] is always nil is a consequence of [] expanding to (fn (_) ()) and nil being the empty list in Arc.

  arc> (macex '[nil])
  (fn (_) (nil))
  arc> ([nil] 3)
  Error: "Function call on inappropriate object nil ()"

-----

2 points by absz 6162 days ago | link

I agree with your general premise, but I have one correction--in arc0.tar, [...] expands directly to (fn (_) (...)). It's only in the git repository that it expands to (make-br-fn (...)) (which (semi-incidentally :P) I added, but that's not the point). Regardless, your point still stands, and I agree.

-----

1 point by sjs 6162 days ago | link

Thank you for the correction. While spouting all that I forgot about the extra stuff that make-br-fn does.

-----

1 point by almkglor 6162 days ago | link

make-br-fn allows you to use _1 _2 ... _n (it searches for the n AFAIK) as well as __. If you use _n you get a n-arity function. If you use _n and __, you get a >=n-arity function, with __ containing the rest. I have a few reservations about whether it handles checking of free variables properly but I haven't actually dived into the code.

-----

1 point by absz 6162 days ago | link

make-br-fn doesn't search for a literal _n, but it searches for anything matching the regexp /_(\d+|_)?/, except for anything of the form /_0+/. The free-variable checking code is based off of problems I did while working through Essentials of Programming Languages by Friedman, Wand, and Haynes, and it certainly shouldn't break in most common cases (especially since most common cases won't bind any extra variables). A second set of eyes is probably a good idea, though.

-----

1 point by treef 6162 days ago | link

Having some thing like this for [] might be sufficient

   (fn (_ . ...) ( prn (... 2))))

-----