Arc Forumnew | comments | leaders | submitlogin
1 point by akkartik 4042 days ago | link | parent

Just spotted your comment while I'm working on something else. Haven't digested it all, but judging from the first five words -- feel free to revert! It was definitely intended as an experiment, and I'm not attached to it. I may well do so myself later today if you don't get to it first.


1 point by akkartik 4042 days ago | link

Ok, done reading now, and you're right, I'll revert it.

I can only defend myself against the wart section :) In wart the pipe operator can only take two args and is intended to be used in infix. I use a non-infix transform for more args, and for prefix mode in general: https://github.com/akkartik/wart/commit/ec0f9a38b8

My weak defense for the rest: functionize and the _ syntax was only intended for tiny expressions.

-----

2 points by rocketnia 4041 days ago | link

"I can only defend myself against the wart section :) In wart the pipe operator can only take two args and is intended to be used in infix. I use a non-infix transform for more args, and prefix mode in general"

Oh, so you're pursuing both options at once. I look forward to you figuring out what kind of indentation you prefer here. :) My "considerations about wart" section was only wishy-washy anyway.

---

"For the rest, my weak defense is that functionize and the _ syntax is only intended for tiny expressions."

In Penknife, when I used the a'b operator as sugar for (b a), I found I ended up with a few really long lines of a.b.c'd'e.f, so it kinda suffered from its own success. ^_^ My a'b is the same as your (a -> b._), and it exactly corresponds to your no-underscore special case, (a -> b), so I expect you to have the same issue.

I suspect these syntaxes actually have a special tendency to let sugar accumulate, driving them away from the ideal "tiny expressions" case. Specifically, they make it possible to inject new code without breaking apart the surrounding sugar first:

  a.b.f.c.d                  # before refactoring
  a.b."foo".c.d              # illegal
  a.b -> (_ "foo") -> _.c.d  # legal? (not quite the example you gave)
  a.b'[itfn:it s.foo].c.d    # Penknife code of similar generality
Fortunately for wart, its infix operators allow whitespace in between, which possibly means you can write these long expressions on multiple lines. (That wasn't the case in Penknife.)

-----

1 point by akkartik 4041 days ago | link

"I look forward to you figuring out what kind of indentation you prefer here. :)"

Here's my current thinking: https://github.com/akkartik/wart/blob/aec0af2676/082macex.wa...

"these syntaxes actually have a special tendency to let sugar accumulate, driving them away from the ideal "tiny expressions" case."

Definitely. The wart example you gave is indeed legal, but the actual _ expression is still simple, even though the chain is long.

It seems nested expressions often work fine because each macro only wraps its arg and leaves the rest to the inside.

  (zap (map car._ _) (list list.1 list.2)
  => (zap (fn(_) (map car._ _)) ..)
  => (zap (fn(_) (map (fn(_) car._) _)) ..)
But that's less readable than when you have the [] delimiting scopes.

Some other concrete examples I came up with of the problems you pointed out:

  (zap (cons? & (fn(_) ..)) ..)  # broken by nested scope
  (zap (cons? & (fn(x) (+ '_ car.x)) ..)  # broken by quoting

-----

1 point by akkartik 4041 days ago | link

It's out, and I'm not putting it back or anything, but FWIW:

  (mac functionize (expr)
    (if (and (treemem '_ ssexpand.expr)
             (~caris expr 'make-br-fn)
             (~caris expr 'fn))
      `(fn(_) ,expr)
      expr))

  arc> (= x '((1) (2) (3)))
  arc> (zap [map [car _] _] x)
  arc> x
  (1 2 3)
This idea was in the wart version from the start (https://github.com/akkartik/wart/commit/7e5d620b28#diff-1) but I didn't mention it for simplicity, and then totally forgot to carry it over into anarki.

It's still pretty hacky though, and has more in common with C's macros than with lisp's.

-----