On Wednesday, June 17, 2015 at 5:52:20 AM UTC-7, Darij Grinberg wrote:
>
> I have a feeling that at least one reply to this message will try to 
> justify the status quo by claiming that users cannot be expected to go 
> search the doc for the right constructor, that the current syntax is the 
> simplest / most intuitive and is what people are used to; etc.
>

Here is that response then. For the most part, matrix does work nicely and 
I really appreciate the typing it saves.

I think a good interface design pattern here is:

 - provide the basic object constructors, with a very rigid, unambiguous 
input structure. When you use these, you know exactly what is going to 
happen because the system doesn't have to guess at all. For matrices, this 
should probably be the constructors belonging to the various matrix spaces.

 - provide on top of that convenience constructors that do make some effort 
to try and understand what you mean. That would be "matrix". A corollary is 
that this routine will occasionally get it wrong and sometimes necessarily 
so. I would not want to do away with the convenience of "matrix" because it 
doesn't work for some more complicated constructions. In those cases the 
users should be smart enough to go and read the documentation and look up
the right constructor. The "matrix" doc would ideally have some pointers.

The problem with matrix(n,n,c) is that it's actually coming from matrix 
rings! Scalars should probably coerce in there to make A - 1 work. It's 
something supported on a level below.

Oddly enough, it's matrix(n,m,<callable>) that's the hard signature to 
recognize there.

It seems we have the following signatures.

[1] matrix([ring],n,n,<scalar>)
[2] matrix([ring],n,m,<callable>)
[3] matrix([ring],[n,[m]],<iterable>)
[4] matrix([ring],[n,[m]],<iterable producing iterables>)

The last one includes matrix(ZZ,n,m,[[1,2],[3,4]]) which I think is 
completely unambiguous, so that input should not be mistaken for something 
else.

In particular, the following element matches all four:

sage: R.<x>=QQ[]
sage: S.<y>=R[]
sage: F=x*y*x
sage: F=x*y+x
sage: F(1,1) ##callable, with the right arity
sage: list(F) ##iterable
[x, x]
sage: map(list,list(F)) ##iterable producing iterables
[[0, 1], [0, 1]]

We end up with sage choosing option [1]:

sage: matrix(2,2,F)
[x*y + x       0]
[      0 x*y + x]

but the other ones would work too:

sage: matrix(2,2,lambda i,j: F(i,j)) #sage doesn't actually check 
"callable" but looks for specific types
[0 1]
[0 2]

sage: matrix(list(F)) #we're not actually looking for iterables: they need 
to be lists or tuples
[x x]

sage: matrix(map(list,list(F)))
[0 1]
[0 1]

so ... yeah ... with our current rules, taken with appropriate ducktyping 
interpretation, we have input that could specify 4 (different!) matrices.

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-devel.
For more options, visit https://groups.google.com/d/optout.

Reply via email to