Martin Coxall <pseudo.m...@me.com> writes:

> I might try to knock up "optional parens inference for Clojure" and
> add in some manner of curly infix as an exercise. It doesn't look like
> it will be too hard. Since {} is taken for literal maps, I'd need
> something else for curly infix. [|...|], %...%, $...$? 

Let's just try a few example functions from contrib.

  (defn subset?
    "Is set1 a subset of set2?"
    [set1 set2]
    (and (<= (count set1) (count set2))
         (every? set2 set1)))

Drop the outer parens.

  defn subset?
    "Is set1 a subset of set2?"
    [set1 set2]
    and (<= (count set1) (count set2))
        (every? set2 set1)

Lets break after "and" so we can drop some more parens.

  defn subset?
    "Is set1 a subset of set2?"
    [set1 set2]
    and
      <= (count set1) (count set2)
      every? set2 set1
  
Now lets introduce infix with say, |...|.

  defn subset?
    "Is set1 a subset of set2?"
    [set1 set2]
    and
      |(count set1) <= (count set2)|
      every? set2 set1

Maybe they need spaces?

  defn subset?
    "Is set1 a subset of set2?"
    [set1 set2]
    and
      | (count set1) <= (count set2) |
      every? set2 set1

Has that suddenly made things more readable?  Maybe.  I don't know.  It
certainly felt really weird writing it.  That "and" by itself does
remind me of Haskell.  The code is definitely looking very tree-like
now, maybe that's a good thing?  My eyes *are* jumping to the "words"
easier and it's definitely less noisy.

Yet, this no longer obviously looks like a list.  Is that bad?  I don't
know.  Do we need to be constantly reminded our code has a list
representation?  Does it make macros harder to think about?

Lets try some more examples.  How about arity overloading?

  defn reductions
    "Returns a lazy seq of the intermediate values of the reduction (as
     per reduce) of coll by f, starting with init."
    [f coll]
      if (seq coll)
        rec-seq self (cons (first coll) (map f self (rest coll)))
        cons (f) nil
    [f init coll]
      rec-seq self (cons init (map f self coll))

Or a macro?

  defmacro rec-seq 
    "Similar to lazy-seq but binds the resulting seq to the supplied 
     binding-name, allowing for recursive expressions."
    [binding-name & body]
    `let [s# (atom nil)]
       reset! s# (lazy-seq (let [~binding-name @s#] ~...@body))

It becomes weirdly tempting to insert more line breaks just to get rid
of the rest of the parens.

  defmacro rec-seq 
    "Similar to lazy-seq but binds the resulting seq to the supplied 
     binding-name, allowing for recursive expressions."
    [binding-name & body]
    `let [s# (atom nil)]
       reset! s#
              lazy-seq
                let [~binding-name @s#] ~...@body

Hmm.  Have we solved anything?  Will this just make the complaints go

(from (too (many (parens))))

to
  too
    many
      nesting
        levels?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to