From: bevan@cs.man.ac.uk (Stephen J Bevan)
Newsgroups: comp.lang.misc
Subject: Re: Scientists as Programmers (was Re: Small Language Wanted)
Date: 30 Aug 92 14:23:17 GMT
Organization: Department of Computer Science, University of Manchester
In-reply-to: mbk@lyapunov.ucsd.edu's message of 30 Aug 92 03:14:34 GMT

In article <17peeqINNkg8@network.ucsd.edu> mbk@lyapunov.ucsd.edu (Matt Kennel) writes:
   [ Matt accepts the multiple value return syntax ]

   : foo b c = array bds vs
   :   where
   :     vs = [ (i,j) := f i j | (i,j) <- range bds, i <= j ]
   :     f i j = sum [ b!(i,k)*c!(j,n,k) | k <- range (klb,kub) ]
   :     bds = ((ilb,jlb),(iub,jub))
   :     ((ilb,klb),(iub,kub)) = bounds b
   :     ((jlb,_,_),(jub,n,_)) = bounds c

   This is perfectly ridiculous!  I have no clue what that means.

array <bounds> <elements>  - create an array with the given _bounds_
                             (as a tuple of lower and upper bounds)
                             and _elements_ (a list of the elements)
b!(i,k) - same as b(i,k) in your notation
sum <list> - sum over all elements in the list
[ <expr> | <control> ] - create a list of exprs, one for each value
                         defined by _control_
<index> <- range <bounds> - assign _index_ each value in the range of
                            the _bounds_
bounds <array> - return the bounds of the array as a tuple.
<index> := <value> - assign _value_ to the given position in the array

For a more detailed definition find a Haskell manual, the easiest
place for most people would probably be in either the April or May
edition (I can't remember) of SIGPLAN Notices.


   I don't think one should have to write a subroutine to implement each simple
   array statement.

You don't _have_ to, I chose to do it that way.  If you want it as an
expression, then you can have it as an expression, but it doesn't
become much shorter :-

  a = array bds [ (i,j) := f i j | (i,j) <- range bds, i <= j ]
    where
      f i j = sum [ b!(i,k)*c!(j,n,k) | k <- range (klb,kub) ]
      bds = ((ilb,jlb),(iub,jub))
      ((ilb,klb),(iub,kub)) = bounds b
      ((jlb,_,_),(jub,n,_)) = bounds c

You can even stuff the function _f_ inline if you want, but IMHO it
gets pretty unreadable if you do.  The part that takes the most space
is the last three lines which determine the bounds for the arrays.
However as you note, you want this done automatically for you so you
probably consider it as unnecessary detail.  I can't help on that, but
then where do you put the bounds information in your notation if you
don't want to iterate over the whole matrix.  For example in Choleski
factorization, Hermite Interpolation or Cubic Spline interpolation
(guess what I wrote recently :-)


   What's called "implied summation convention" means "sum over repeated
   indices"on the right hand side of the assignment
   and iterate over covarying indices on both sides.  (No I didn't invent
   this...heard it's also called "Einstein summation convention" as it's
   very useful in relativity calculations).

It certainly is a concise notation, but isn't it a bugger to spot
errors when using this notation?  For example, I once spent 2 hours
trying to find a bug in a program which was due to having a variable
called _a'_ when it should have been _a''_.  The prime convention
works fine in small formulae on paper, but I don't think it translates
well to programs, so now I avoid it even if the language allows me to
do it.  Note this should not be construed as me telling scientists
that their notation is all wrong, it is just a warning that nice
implicit notations on paper don't always transfer well to programs.
With that in mind, I'd probably write :-

   T(i) = C(i,j,j)

as 

  t = trace c

and hide all the details in _trace_.  However, I'm sure this is
anathama to any scientists.


   I think it wouldn't be so bad to allow you to explicitly say these things:

   for all i T(i) = sum_over(j) C(i,j,j)

Well the best I can do for this is :-

t = array (m,n) [ i := sum [ c!i!j | j <- js ] | i <- is ] 
  where
    js = range (jlb,jub)
    is = range (m,n)
    ((m,jlb,_),(n,jub,_)) = bounds c

and even then the c!i!j stuff may be wrong :-<

BTW, what happened to the complex variable or exponential notation,
was the above so bad that it wasn't even worth discussing?

bevan
Xref: sparky comp.lang.misc:2862 comp.theory:1852 comp.lang.prolog:1633 comp.lang.functional:1055 comp.ai:3294