Arc Forumnew | comments | leaders | submitlogin
Pipes and s-expressions
3 points by akkartik 4893 days ago | 16 comments
Here's a speculative idea:

  | x | y | z ; => (z (y x))

  | 34 | * _ _ | + _ 1 ; => ([+ _ 1] ([* _ _] 34))
Basically get the reader to process everything between '|' and newline. And perhaps we shortcut [x] to [x _]. Append a trailing '_' if there's no '_'.

(I know we use | for other things right now.)

Anybody interested in an arc-based shell? :)



1 point by Pauan 4892 days ago | link

Yes! I've written shell scripts in Arc, and I've noticed that the Unix concept of pipes (and especially the syntax for them) is very elegant and concise.

But why not just make it a binary operator, like in Unix?

  x | y | z
  (z (x y))
I'll note that this would solve a problem I've been having... In particular, notice this pattern:

  (w/foo 1 (w/bar 2 (qux)))
The above could be written as this, instead:

  (qux) | w/bar 2 | w/foo 1
Hm... perhaps the bars should be reversed, so it would be like this:

  w/foo 1 | w/bar 2 | (qux)
I've had some situations where I kept wishing I had some syntax to make them shorter, but I wasn't sure exactly what kind of syntax would help...

-----

1 point by akkartik 4892 days ago | link

..why not just make it a binary operator..?

Hmm, you mean an infix operator, right? I'm not sure how to fit an infix operator into an otherwise prefix language. I'm sure lots of questions arise. Operator precedence, where the right-hand arg terminates. If there's a simple model that answers those questions well that would be great.

-----

1 point by Pauan 4891 days ago | link

Yes. One potential solution is the curly infix system described here (scroll down a bit):

http://www.dwheeler.com/readable/sweet-expressions.html

Though that does add two extra characters:

  {x | y | z}

-----

1 point by akkartik 4891 days ago | link

Ah, I keep losing that page, thanks!

But for this particular case I'd rather just add an extra '|' and make it all prefix.

-----

2 points by akkartik 4881 days ago | link

The new wart interpreter (http://arclanguage.org/item?id=14881) no longer reserves '|' for syms. It also lets you skip parens and use indent if you choose.

  wart> assign f 3
  wart> f
  3
  wart> assign f (lambda() 34)
  wart> (f)
  34
  wart> def f()
    35

  ; extra <enter> like python
  wart> (f)
  35

-----

3 points by davidx 4882 days ago | link

It would probably be better to keep the shell semantics so that

  ( x | y | z )
  =>
  (z (y (x)))
and

  ( a b c | x y z )
  =>
  (x y z (a b c))
Ie, first subexpression is also treated as a function call.

-----

4 points by rocketnia 4882 days ago | link

Well, in that case I've got some deja vu. :-p http://arclanguage.org/item?id=13450

Here's a quick macro to emulate this syntax:

  (mac // body
    (aif (pos ': body)
      (let (before (nil . after)) (split body it)
        `(,@before (// ,@after)))
      body))
Now instead of writing this:

  (accum acc
    (each x args
      (acc (* 2 x))))
You can write this:

  (// accum acc :
     each x args :
       acc : * 2 x)
I've also put this macro in a gist at https://gist.github.com/1078269.

Better naming ideas are welcome. :-p

-----

1 point by davidx 4882 days ago | link

Well, I prefer the left-to-right dataflow, but that might just be force of habit, and this version is a lot cleaner and simpler to implement. Not sure about '//' for the macro name (looks like division), but this looks the best way to do this.

-----

1 point by rocketnia 4882 days ago | link

Ah, make that deja vu and egocentrism-based dyslexia. ><;

Implementing the pipeline left-to-right order is just a matter of switching "before" and "after," I think.

Hmm, macros and special forms seem a bit confusing that way around... but maybe they'd just look like list comprehensions or something. What about having both operators? What might their precedence be like?

As far as naming goes, I was trying to pick something unused that would appear to be part of the parenthesis in some way. :-p

-----

3 points by davidx 4882 days ago | link

Maybe

  (<< a b c : x y z) => (a b c (x y z))
  (>> a b c : x y z) => (x y z (a b c))
then? Still looks slightly like less-than/greater-than, but this gives a visual cue for data direction, and avoids needing to care about relative precedence.

-----

1 point by rocketnia 4881 days ago | link

Reminds me a bit of monads, bit shifting, and strict comparison. >.>; I guess maybe there's not an unimpeachable choice here. :-p

I was thinking along the lines of putting them in the same syntax:

  (// a b c :
    x y z ! i j k)
  =>
  (a b c (i j k (x y z)))
Then again, yours does allow for this:

  (<< a b c :
    >> x y z : i j k)

-----

1 point by zck 4880 days ago | link

Fyi, your other comment on this thread (http://arclanguage.org/item?id=14886) is dead. It was obviously a valid post, but it apparently tripped the detector.

-----

1 point by rocketnia 4880 days ago | link

I didn't see it while it was alive, so I'm curious. ^_^

-----

1 point by akkartik 4880 days ago | link

Perhaps it was deliberately deleted? I can resuscitate it if not.

-----

1 point by davidx 4879 days ago | link

I think that was a duplicate that I deleted.

-----

1 point by Pauan 4882 days ago | link

I agree.

-----