[Grace-core] minor language issues

Andrew P Black andrew.p.black at gmail.com
Mon May 18 09:56:56 PDT 2015


On 17 May 2015, at 22:39 , James Noble <kjx at ecs.vuw.ac.nz> wrote:

>> My thoughts, for what they are worth!
> 
> always good! 
> 
> 
>>> - should spaces be required around operators?
>>> e.g. should "1+2" be legal, or should we be required to write "1 + 2".
>>> requiring spaces solves a bunch of issues wrt brackets & generics
>> 
>> No, we should not require spaces, except around < and >
> 
> that's what I originally thought, but I don't like the exceptions for "<" etc.
> I'm slowly coming around to the "all spaces, all the time" position. 

The problem that you are identifying comes from trying to use < and > as brackets, not from 
not allowing x+1 as an expression.   If you are not happy with teh exception for < and >, then let's use
some real brackets instead of < and >.

>>> - should more than statement be permitted on a line?
>>> e.g. should "a;b;c;" be legal, or should we have to break the lines, thus:
>>>  a
>>>  b
>>>  c 
>> 
>> Yes.
> 
> I think so too.
> 
>> 
>>> - there's no way to pass *no* varargs parameters. 
>>> given a multi-part method with varargs we can't call then with
>>> no arguments, because "()" is supposed to be illegal.
>> 
>> I think that this is a misapprehension.
> 
> I don't - we've talked about "()" especially being always and everywhere *illegal*.
> so I don't want to lose that.   And I don't like the JS/C/BCPL conventions where
> writing "foo" gets you the reified method for foo, while "foo()" calls it!

I think that you are mis-remembering the discussion, but since we have been very bad
at documenting discussions, I can't be sure.  I certainly agree that we talked about the 
C and BCPL convention where empty brackets are used to distinguish between referencing
a function and invoking the function, and I agree that we decided that we didn't want to do that,
mostly so that field accesses and method requests had the same syntax.

But that's a completely different topic fro the current topic, which is how to construct an argument
list of length zero.   () seems like a perfectly rational way of doing this.  In fact, I can't think of
another way of doing it — and I'm guessing that you can't either, or else you would have
suggested it.   What's the problem with using () for a zero-length sequence of arguments?
> 
>>  A method that takes a variable number of arguments can clearly take zero arguments, and 
>> () is a reasonable way to write them
> 
> well yes, but so is "foo" with no arguments....

Here I disagree.  That's like saying that   is a reasonable way to write 0.   It sounds superficially reasonable, 
but it held back civilization for roughly a thousand years.
> 
>> .   Similarly, a method that  is declared as
>> 
>> 	method  foo(a, b, *c)
>> 
>> can be requested as foo(1, 2), foo(1,2,3), and foo(1,2,3,4) , but not as foo(1).  In foo(1, 2), c is bound to an empty sequence.
> 
> right. 
> 
>> What we agreed was illegal is requesting a method declared as
>> 
>> 	method none { … }
>> 
>> by writing obj.none(), since the method is being given an argument list but has no parameter to bind to it.
> 
> yep, I agree that should be illegal.
> 
>> I see nothing wrong with requesting 
>> 
>> 	method variable(*a) { … }
>> 
>> as obj.variable(), since here the method `variable` is being given a parameter list of length zero which is bound to the sequence argument a.
>> A sequence of length zero is a perfectly respectable operation.
> 
> except it's not really a sequence, and it's yucky...

Why do you say that it's not a sequence?  It walks like a Sequence, quacks like a Sequence, swims like a Sequence ... to me, that makes it a sequence.  Isn't the essence of structural typing that behaviour is all that matters?

And what oracle told you it was "yucky"?   What entrails did she read?

>> I think that the real question is whether it’s legal to request
>> 
>> 	obj.variable
>> 
>> with no argument list at all.  In general, it’s a mistake to confuse zero with blank space, or an empty collection with no collection.

They say the pagan has invented a number which is nothing—nought—written 
like an O, a hole, an oblivion.  I could clutch that nothing to my breast.

		Sir Kay, in The Acts of King Arthur 
				  and His Noble Knights
					    John Steinbeck

> 
> indeed - but again, it's not really a "collection".

Again, why say that?   If it is not really a collection, what is it?

> If we commit to some collection syntax (see notes on bracketing below)
> we could consider removing varargs altogether and just using explicit collections.
> optional method parts could help here too.
> 
>> Why should methods with multiple argument list be different form those with a single argument list?
>> 
>>> e.g. x.foo(1) foo(11)  and x.foo(1,2) foo(11,22) are both legal, but x.foo() foo()  is not. 
> 
> in general, they shouldn't be. 
> 
>> x.foo() foo() seems perfectly reasonable to me, if the method in question was declared as
>> 
>> 	method foo(*a) foo(*b)
>> 
>> If it wasn’t, we would get a dynamic error when foo()foo() is invoked with the wrong number of arguments.
> 
> or should we write it  x.foo foo 

That makes no sense as an invocation of foo()foo() (although `foo bar` ought to be legal as a request of foo with bar as argument.)
> 
> (note that the current syntax does NOT support this!)

And for good reason.
> 
> 
>>> We don't have this problem with single-part requests because x.foo(1)  and  x.foo are both legal requests
>> 
>> Yes, they are both legal requests.  What’s not clear to me is if x.foo is a legal way to call a method declared with a parameter list.
> 
> right. so we need to clarify that.
> 
> 
>>> I don't think operator requests can take varargs.
>> 
>> I think that all infix operators take exactly 1 argument, and all prefix operator take exactly 0 arguments.
> 
> agreed...
> 
>> 
>> I’ve been wondering about allowing [ and ] and indeed any matched pair of brackets other than { and } and ( and ) to be declared as 
>> methods.  If so, can they be variable arity methods?   It would certainly be convenient to allow matched brackets of any available kind to
>> be used as factory methods for sequences, sets, etc.
> 
> I'm afraid you and Michael have been thinking alike again. 
> 
>> On another, but related, tack, I’ve been thinking about how to eliminate the arity checks that currently happen on every method request.
>> This would be easy if it were not for variable arity methods.   But so long as we have them (and I don’t see a good alternative),  we will
>> need a slow path to deal with them.
> 
> right. other than hope?    or caching?   or PyPy? 
> 
>> It’s also a bit frustrating not to have a way of “exploding” a collection into an argument list (like JavaScript’s Function.prototype.apply()).
>> As with C, every Grace variable arity method really needs to be defined in terms of another method that takes a collection argument.   
>> It’s not terrible, but it’s a place where we have to teach a programming pattern to get around a language deficiency.   Which was one of 
>> the things that we said we wanted to avoid.
> 
> 
> yep.   well we could always steal another operator "prefix *" and add it to the language,
> 
> alternatively (and perhaps this is why I shouldn't answer emails in the pub)
> we could forgo varargs altogether, but bring back brackets or matchfix (circumfix) 
> operators, and just pass in sequences as and where required rather than use varargs.
> the catch is
> 
>> 	method  foo(a, b, *c)
> 
> which can be called 
> 
> x.foo( "A", "B", 1, 2, 3)
> x.foo( "A", "B", 1)
> x.foo( "A", "B")
> 
> would have to become either 
> 
> method foo(a, b, c : Sequence<Number>) 
> 
> and be called
> 
> x.foo( "A", "B", [1, 2, 3])
> x.foo( "A", "B", [1])
> x.foo( "A", "B", [])
> 
> or we could just multiple names (and or definitions)
> 
> method foo(a, b) stuff (c : Sequence<Number>) 
> 
> called as 
> 
> x.foo( "A", "B") stuff [1, 2, 3]
> x.foo( "A", "B") stuff [1]
> x.foo( "A", "B") stuff [] 
> 
> or with an option part, or a second definition
> 
> method foo(a, b) stuff (c : Sequence<Number>) 
> method foo(a, b)
> 
> called as 
> 
> x.foo( "A", "B") stuff [1, 2, 3]
> x.foo( "A", "B") stuff [1]
> x.foo( "A", "B")
> 
> a related question is: if we lose varargs, do we lose too much when it comes to host language interoperation
> given that they do all use varargs?
> 

I think that "host language interoperation" should be the least of our concerns.    
I have thought about getting rid of variable arity methods too,  but have always decided against the idea.  The argument for elimination is that it would simplify the language a little, and simplify the implementation considerably.  Without variable arity methods, the number of parameters in the lists of the receiving method is always known statically, so we could eliminate the checks on arity that currently take place on every request.
Since method request has to be fast in any reasonable implementation of Grace, this is not unimportant.

The downside is that programs become harder to write.  We have to explain to novice students why they have to write 

x.foo( "A", "B", [1, 2, 3])

rather than

x.foo( "A", "B", 1, 2, 3)

Smalltalk doesn't have variable arity methods.  As a result, it has a kludge every place they would be needed, such as value, value:, value: with:, value: with: with:, ... and finally valueWithArguments:  Not Graceful.

One possibility is to subsume variable arity methods into some more general scheme for methods with regular expressions for for names instead of strings, such as if()then()[elseif()then()]*else().    I know that you are fond of this, and it would eliminate three special cases from the syntax.  But at what cost?

I did have an early syntax where ( and ) always constructed a tuple, and there was a 1-tupling coercion of some sort so that x could be considered to be either a value or a tuple of values of length 1.  In this syntax, all argument lists are of length 1, and methods use a pattern-matching syntax to un-tuple the argument.  (Like Python 2.  Notice that Python 3 dropped this.  Anyone know why?)

Michael, you are very good at thinking through the consequences of design changes.  I would be surprised if you haven't considered dropping variable arity methods and replacing them by something else.   What did you conclude?

	Andrew




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailhost.cecs.pdx.edu/pipermail/grace-core/attachments/20150518/a431b90d/attachment-0001.html>


More information about the Grace-core mailing list