When comparing various syntax options, I find it helpful to try out various 
code fragments to see if they "make sense".  So here are two other examples 
I've worked out.  I did this by hand, so there may be an error or two, but the 
point is to look at it, to see if the results are comprehensible... and if the 
syntax is useful.

One thing I learned from the Matrix multiply example - if {} FORCES an infix 
interpretation, and you don't want to REQUIRE that the "group" operator be used 
everywhere, you really need an unfixed [...] to mean "an s-expression, but keep 
accepting sweet-expressions inside it".  This is in addition to unprefixed {..} 
to FORCE infix interpretation, and unprefixed (...) to force raw s-expression 
interpretation.

So, here are two more examples:add-if-all-numbers and matrix multiply routine 
mat-mat-mul.  The first is typical "few infix operations" but lots of nested 
function calls; the second has many infix operators, and also uses lists of 
lists (e.g., in a do loop):

Question is - which ones are readable/understandable?  Which ones are not?



* Here's a Scheme example from Wikipedia - specifically the article
"Scheme (programming language)".  This example adds an arbitrary
list of numbers, and if a non-numeric value is found in
the list the procedure is aborted immediately and the constant value #f
(false) is returned. This is achieved by capturing the current continuation in
the variable exit and using it as an "escape procedure".

+ Original Scheme:
(define (add-if-all-numbers lst)
  (call/cc
   (lambda (exit)
     (let loop ((lst lst) (sum 0))
       (if (null? lst) sum
         (if (not (number? (car lst))) (exit #f)
           (+ (car lst) (loop (cdr lst)))))))))


+ Sweet-expressions, version 1:
 define add-if-all-numbers(lst)
  call/cc
   lambda (exit)
     let loop ((lst lst) (sum 0))
       if null?(lst)
         sum
         if not(number?(car(lst)))
           exit(#f)
           (car(lst) + loop(cdr(lst)))


+ Infix default, {..} for grouping, [...] disables infix, f(...) function call:
 define add-if-all-numbers(lst)
  call/cc
   lambda (exit)
     let loop ((lst lst) (sum 0))
       if null?(lst)
         sum
         if not(number?(car(lst)))
           exit(#f)
           car(lst) + loop(cdr(lst))

+ Non-Infix default, {..} around all infix:
 define add-if-all-numbers(lst)
  call/cc
   lambda (exit)
     let loop ((lst lst) (sum 0))
       if null?(lst)
         sum
         if not(number?(car(lst)))
           exit(#f)
           {car(lst) + loop(cdr(lst))}



* Matrix multiply example from http://www.scheme.com/tspl2d/examples.html
mat-mat-mul multiplies one matrix by another, after verifying
that the first matrix has as many columns as the second matrix has rows.

+ Original Scheme:
 (define mat-mat-mul
    (lambda (m1 m2)
       (let* ((nr1 (matrix-rows m1))
              (nr2 (matrix-rows m2))
              (nc2 (matrix-columns m2))
              (r   (make-matrix nr1 nc2)))
          (if (not (= (matrix-columns m1) nr2))
              (match-error m1 m2))
          (do ((i 0 (+ i 1)))
              ((= i nr1) r)
              (do ((j 0 (+ j 1)))
                  ((= j nc2))
                  (do ((k 0 (+ k 1))
                       (a 0
                          (+ a
                             (* (matrix-ref m1 i k)
                                (matrix-ref m2 k j)))))
                      ((= k nr2)
                       (matrix-set! r i j a))))))))

+ Sweet-expressions, version 1:
 define mat-mat-mul
    lambda (m1 m2)
       let* ( (nr1 matrix-rows(m1))
              (nr2 matrix-rows(m2))
              (nc2 matrix-columns(m2))
              (r   make-matrix(nr1 nc2)))
          if not(matrix-columns(m1) = nr2) ; f(infix) handled automatically.
              match-error(m1 m2)
          do ((i 0 (i + 1)))
             ((i = nr1) r)
             do ((j 0 (j + 1)))
                ((j = nc2))
                do ((k 0 (k + 1))
                    (a 0 (a + (matrix-ref(m1 i k) * matrix-ref(m2 k j)))))
                   ((k = nr2) matrix-set!(r i j a))

 Or, if you use groups:

 define mat-mat-mul
    lambda (m1 m2)
       let*
         group
           nr1 matrix-rows(m1)
           nr2 matrix-rows(m2)
           nc2 matrix-columns(m2)
           r   make-matrix(nr1 nc2)
         if not(matrix-columns(m1) = nr2) ; f(infix) handled automatically.
           match-error(m1 m2)
         do
           group
             i 0 (i + 1)
           group
             (i = nr1) r
           do
             group
               j 0 (j + 1)
             group
               j = nc2
             do
              group
                k 0 (k + 1)
                a 0 (a + (matrix-ref(m1 i k) * matrix-ref(m2 k j)))
              group
                (k = nr2) matrix-set!(r i j a)


+ Infix default, {..} for grouping, [...] disables infix, f(...) function call,
(...) switches to regular s-expression reader:

 define mat-mat-mul
    lambda (m1 m2)
       let* { {nr1 matrix-rows(m1)}
              {nr2 matrix-rows(m2)}
              {nc2 matrix-columns(m2)}
              {r   make-matrix(nr1 nc2)}}
          if not(matrix-columns(m1) = nr2)
              match-error(m1 m2)
          do {{i 0 {i + 1}}}
             {{i = nr1} r}
             do {{j 0 {j + 1}}}
                {{j = nc2}}
                do {{k 0 {k + 1}}
                    {a 0 {a + {matrix-ref(m1 i k) * matrix-ref(m2 k j)}}}}
                   {{k = nr2} matrix-set!(r i j a)}

 Or, if you use groups:

 define mat-mat-mul
    lambda (m1 m2)
       let*
         group
           nr1 matrix-rows(m1)
           nr2 matrix-rows(m2)
           nc2 matrix-columns(m2)
           r   make-matrix(nr1 nc2)
         if not(matrix-columns(m1) = nr2) ; f(infix) handled automatically.
           match-error(m1 m2)
         do
           group
             i 0 {i + 1}
           group
             {i = nr1} r
           do
             group
               j 0 {j + 1}
             group
               j = nc2
             do
              group
                k 0 {k + 1}
                a 0 {a + {matrix-ref(m1 i k) * matrix-ref(m2 k j)}}
              group
                {k = nr2} matrix-set!(r i j a)

+ Non-Infix default, {..} around all infix, unprefixed [...] is like
(...) but doesn't disable sweet-expressions, f{...} is f({infix}),
(...) switches to regular s-expression reader:

 define mat-mat-mul
    lambda [m1 m2]
       let* [ [nr1 matrix-rows(m1)]
              [nr2 matrix-rows(m2)]
              [nc2 matrix-columns(m2)]
              [r   make-matrix(nr1 nc2)]]
          if not{matrix-columns(m1) = nr2} ; f{infix}
              match-error(m1 m2)
          do [[i 0 {i + 1}]]
             [{i = nr1} r]
             do [[j 0 {j + 1}]]
                [{j = nc2}]
                do [[k 0 {k + 1}]
                    [a 0 {a + {matrix-ref(m1 i k) * matrix-ref(m2 k j)}}]]
                   [{k = nr2} matrix-set!(r i j a)]


 Or, if you use groups:

 define mat-mat-mul
    lambda [m1 m2]
       let*
         group
           nr1 matrix-rows(m1)
           nr2 matrix-rows(m2)
           nc2 matrix-columns(m2)
           r   make-matrix(nr1 nc2)
         if not{matrix-columns(m1) = nr2} ; f{infix} = f({infix}).
           match-error(m1 m2)
         do
           group
             i 0 {i + 1}
           group
             {i = nr1} r
           do
             group
               j 0 {j + 1}
             group
               j = nc2
             do
              group
                k 0 {k + 1}
                a 0 {a + {matrix-ref(m1 i k) * matrix-ref(m2 k j)}}
              group
                {k = nr2} matrix-set!(r i j a)


Reply via email to