As for the exponential operator: That's just not a low level operation.
Surma
But it seems a real shame to go back to the old days of fortran 77,
where we need to recompile our program to solve a problem of a
different size. True, recompiling with go is fast, but then we also
need to use some sort of preprocessing to set the dimensions properly.
Alas, I am reminded of an mpi program written in fortran 77, which
used sh and factor to split the problem between nodes, since this
couldn't be done in the fortran program itself, since it determines
the size of the arrays.
David
That's putting it mildly, and a bit insultingly to Fortran 77, which
really is better at multidimensional arrays than Go is at present. In
Fortran 77, one can write a subroutine that, for instance, multiplies two
matrices which are of arbitrary dimensions (the dimensions being supplied
as parameters to the subroutine), while still using the usual Fortran
syntax for accessing matrix elements. (That is, writing "a(i,j)" to
denote the i,j'th element, rather than needing to write something like
"a(i*n+j)".) But in Go, one has to write something like "a[i*n+j]" --
or, alternatively, use slices of slices, which yields a different
implementation, and for most purposes a slower one (since pointer-chasing
is slow on modern machines).
This seems to me to be completely gratuitous: there's no reason at all
that the language couldn't support multidimensional arrays very well.
I've outlined before how that might be done (while respecting Go's
distinction between arrays and slices, which I think is an excellent one,
and not altering the meaning of any existing Go code):
http://groups.google.com/group/golang-nuts/msg/2ba08fe85b97f441
but didn't get much response. I suppose it's a question of priorities:
when you're in the business of writing multi-thousand-line programs, in
which every other line of code involves multidimensional arrays, being
able to write a[i,j] rather than a[i*n+j] is a feature to kill for. It
is also often important for such codes to be fast, which weighs against
using slices of slices. But to systems programmers, such things can seem
like mere luxuries.
--
Norman Yarvin http://yarchive.net
Norman Yarvin +1
request for multidimensional arrays: +1
It would be instructive to read a response from the developers of Go.
Are multidimensional arrays of low priority and it is only a question
of time/manpower,
or should Fortran users stay where they are, they will never be a
target audience ?
On Jul 31, 6:55 am, Norman Yarvin <yar...@yarchive.net> wrote:
> On Wed, Jul 28, 2010 at 06:14:03AM -0400, David Roundy wrote:
> Why is is so bad to have to declare your
>multi-dimensional array at compile-time?
The problem isn't that you have to declare it per se, but that you have
to decide exactly what its dimensions are at compile time. You can write
a routine to multiply two 10x10 matrices, using Go's existing arrays of
arrays; but if you want to generalize that routine so that it multiplies
two NxN matrices, you're out of luck: you have to rewrite it to use a
different sort of data structure (slices of slices), and have to change
all the callers of the routine so that they pass in such a data
structure. The situation is somewhat like what Brian Kernighan
complained about in section 2.1 of "Why Pascal is Not My Favorite
Programming Language":
http://www.lysator.liu.se/c/bwk-on-pascal.html
except here the complaint only applies to multidimensional arrays; for
one-dimensional arrays, Go's slices provide a very nice way to deal with
them. It's just that presently, there is no such thing as a
multidimensional slice. Go, in this respect, provides about the same
functionality that C did before C99, where the first dimension of an
array could vary at runtime, but subsequent dimensions had to be fixed at
compile time. You could write the function declaration:
void f(double a[][10], int n)
{
....
but not
void f(double a[n][m], int n, int m)
{
....
as you can at present. If you wanted the latter sort of functionality,
the only way to get it was to use pointers to pointers: the function
would be declared as:
void f(double **a, int n, int m)
{
....
and what would be passed in would not be a pointer to a section of memory
containing n*m doubles, but rather a pointer to a section of memory
containing n pointers, each of which pointed to one row of the array.
>The reasoning behind the questions: slices of slices don't inherently seem a
>slow or inefficient construct with proper compiler support [...]
They really are. Slices-of-slices multidimensional arrays are
implemented in much the same way as pointer-to-pointer multidimensional
arrays are in C, the main difference being that the extra array contains
not only pointers, but also capacities and lengths -- the other
attributes of a slice. This is, in most respects, a more flexible data
structure: not only can each row of the array be allocated in a place
completely unrelated to where other rows of the array are stored, but in
addition, each row can have a different length. That flexibility can be
useful... but it has a cost. It means using an entirely different memory
layout from traditional arrays, where an N by M array consists of a
continuous hunk of N*M entries. Even if, in practice, the data is always
going to be laid out in a continuous hunk, and the lengths of the rows
are always all going to be the same, the compiler generally can't know
that: instead it has to generate code for the general case -- doing
bounds checks for each row that is accessed, for instance, where if it
knew all the rows were the same length, it would only have to do the
bounds check once.
But the main cost is that of retrieving and following pointers, which is
a relatively slow operation on modern machines. Doing a multiplication
to calculate the position in memory of an array element is generally
faster than retrieving a pointer from which to calculate that position.
Also, with a continuous hunk of memory, the compiler can implement taking
a submatrix using a trivial amount of arithmetic. If, for instance, one
singles out a submatrix consisting of rows 2 through 4 of columns 3
through 6 of an N by M matrix -- what I'd write as a[2:4,3:6] -- the
compiler just implements that by adding 2*M+3 to the base pointer to the
matrix, setting the first dimension to three, the second dimension to
four, and the stride to M. With pointers to pointers (or slices of
slices), selecting the same submatrix would require allocating and
filling a new pointer array -- which is, in my opinion, too much of a
heavyweight operation for it to be good for the compiler to do it
automatically for you.
It's not entirely inconceivable to write a compiler that would look at a
program using slices of slices, figure out that it really could have been
written as operations on continuous hunks of memory, and compile it that
way, as an "optimization". But writing such a compiler would be vastly
more difficult than writing a compiler that implemented both sorts of
data structure, and just did whatever the user told it to do.
> The only arguments I see are that defining arrays at
>runtime is nice (true), and having a [i,j] syntax is nice (true). However,
>the second thing also makes the language's syntax more complex, and the
>first makes panicking at runtime likely (finding a contiguous block of RAM
>1gb big is next to impossible, without moving everything around, which the
>OS might do, but there's no guarantee it won't fail, or worse, silently
>fail).
Finding a monster-sized chunk of contiguous memory is a battle that one
faces in any language where memory is allocated and freed. But
multidimensional arrays don't necessarily have to be monster-sized.
>Also, what I'm really seeing here is not people looking for
>multi-dimensional arrays (things that Go already supports), but rather that
>multi-dimensional arrays be as easy to build and use as normal arrays, while
>separating the length of the array from the type, so that it can be changed
>or defined at runtime. It all just seems a bit superfluous to me, is there a
>reason outside of convenience?
Convenience, though often sneered-at, is a great force in this world.
It's why we don't use Turing machines to do computing with.
David