[Grace-core] Further questions on the specification

Andrew P. Black black at cs.pdx.edu
Wed May 25 11:17:10 PDT 2011


On 25 May 2011, at 10:17 , Kim Bruce wrote:

>> 
>> - Tuple unpacking in method calls
>> Section 9.1 says "multiple parenthesized arguments are treated as a
>> single tuple argument". What does that mean? How do you declare a
>> method that takes this tuple argument, distinguished from one that
>> really does take one argument?
> 
> Tuples were added a bit late, so we haven't thought them through.  Most functional languages treat all functions as taking a single argument, which may be a tuple.  If they are not in parentheses then they are assumed to be curried.  I'm not quite sure how this would interact with our mixfix notation for methods and method calls.  This is something that we should address in more detail.

What I had in mind when I wrote this was as follows.  I obviously didn't make it very clear; I hope this is better, but if not, ask again.

[Note on terminology: the specification in the heading of a method is called a parameter.  The value that is passed to the message request is called an argument.]

If a method is defined as taking a parameter (a:R, b:S, c:T) then it should be given a 3-tuple of type (R,S,T) as argument.  If it's given a 2-tuple or a 4-tuple than that's an arity error (which I would expect even the dynamically-typed variant to trap statically in the case that the argument is a literal tuple).   If the method is given a 3-tuple of a different type, then that's a type error, which would be caught statically or dynamically, depending.

If you declare a method that takes one parameter p, of type Number, say, and a method request provides instead a tuple of three numbers (4, 5, 6), then that's a compile-time arity error.    If you declare a method that takes one parameter p of unspecified type, and call it with argument (4, 5, 6), then everything will work fine if the code treats p as a sequence (p map fun, p.size, for p do etc.), but if the code attempts an operation that is not defined on sequences (like  p = 0) then a run-time type error will be generated.

>> 
>> - Tuples generally
>> Section 5 says that "(7)" is "the number 7, which is also a 1-tuple
>> containing 7". Does that mean that all objects support the tuple
>> interface, or is the type of the expression to be inferred by context?

If the argument is (4), I felt that had to be equivalent to an argument of 4.   If these two forms are not equivalent, then we will have to use some other kind of bracket for tuples.   I think that the implication of this is that 4 will have to be treatable as a sequence of length 1, as well as a number.   Will this have untoward consequences?  I don't know; we will have to see what happens.

Another option would be to treat (4) as both a Number and a 1-tuple, but to treat 4 as just a number.  So 4 and (4) are not exactly the same.  This might also have untoward consequences.

In answering the question "Does that mean that all objects support the tuple
interface, or is the type of the expression to be inferred by context?" I would have said "yes", because I see these things as independent.  I'm not clear what the difference is between all objects supporting he tuple interface and the type of an expression being inferred from the context.  Can you give me a specific example where the answer will be different depending on which I pick?

> In general, most languages treat different arity of tuples as distinct data types.  I.e., 1-tuples are not the same type as 2-tuples.  That seems right to me.  (Though the specification section 5 seems to hint otherwise!)  

I agree that 1-tuples are not the same type as 2-tuples.  What in Section 5 hints otherwise?

> On the other hand, it might be handy to treat 1-tuples of type T as implicitly coerceable back and forth to elements of type T.  That makes me a bit nervous, however.  I assume the main issue here is with omitting parentheses in method/function calls and with getting back multiple values.  (As I noted in an earlier e-mail, I'd rather not see the a,b,c := o.getVals(...) as being allowed -- I'd require (a,b,c) := o.getVals(...).)

I didn't see that email, sorry.   I don't have a problem with requiring parens on the l.h.s. of an assignment or an initializing declaration.  However, this is an independent question: the thing on the l.h.s. is not a tuple, it's a pattern (binding construct) of some kind.
> 
> I think we need to talk this through in more detail as to why we need both lists and tuples, and if we do, what their different interfaces should be!

Lists would be a library-defined data type, implemented using finger trees or something similar for the immutable variant, and maybe cons cells for the mutable variant.   The place where this relates to tuples would be that one could create a list with method request like List.from(2,3,5,7,11,13).   The argument would be nothing more than 6 values on the stack, along with a length.   The object constructor would build the library-defined data structure for List using these values — that is, it would copy them into the finger tree or the cons cells, for example.   I don't see any redundancy here; maybe I'm missing something.

	Andrew







More information about the Grace-core mailing list