On Tue, 2008-07-08 at 12:39 -0400, Swaroop Sridhar wrote:
> I actually don't understand this problem correctly. My understanding was
> that both the actual and formal arguments are converted into pairs the
> same way.

Yes.

> So, the arity of all functions is always one.

Yes. That is the problem that we are trying to solve.

> I don't see the ambiguity
> in the resolution of pattern matching here.

There is no ambiguity in the formal sense. There is no ambiguity in the
behavioral sense.

But the absence of ambiguity is not the same as the absence of surprise.
A C programmer who writes:

  (define (f x y)  (pair x y))

expects that the invocation

  (f 1:int32 #\c "abc")

will generate a compile-time error. That is: programmers coming from
conventional languages expect that agreement between the number of
expected arguments and the number of arguments actually presented will
be checked by the compiler.

>From this perspective, the problem with re-introducing pair-consing is
that it defeats the ability of the compiler to check parameter arity
agreement.

So I am looking for a way to re-introduce pair consing *without* losing
that.

The reason this does not arise in ML is higher-order functions, but we
are trying not to introduce syntactic constructs that induce unnecessary
dynamic allocation.

> Further, this is not really varargs. For the function
> 
> (define (f x:int y)  <body>)
> f: (fn (int, 'a) 'b)
> 
> we can apply any number of arguments at the call site...

Yes. This has the syntactic *appearance* of varargs, but all of the
vararg-ness is handled at compile time. In short, you get all of the
advantages of varargs and none of the costs.

But this is not good if the cost is an inability to check actual/formal
arity agreement.

> So, I think that this is different from the overloading in the number of
> arguments as in C++, since in that case, all arguments are namable by
> pattern matching, and therefore usable in the body of the function.

Actually, it is exactly the same. C++ procedures can be viewed
*logically* as single-argument procedures in exactly the way that we are
discussing here.

> > But I am considering the following syntax modification:
> > 
> >    1. In the lambda form, add the ability to write:
> > 
> >           (lambda (x y ...) body)
> > 
> >       with the intended meaning that there is no maximal
> >       expected arity for this procedure.
>
> For the function
> (define f (lambda (x y ...) body))
> 
> do we give f the type (fn ('a 'b `dyn) 'c)

Certainly not (shudder with horror)!. In my original proposal, we would
give f the type:

  f: (fn (pair 'a 'b) 'c)

in my later refinement (the one where only ... implies pair-consing), we
would give it the type:

  f: (fn ('a (pair 'b 'c)) 'd)

> If this is the case, is the difference between apply and apply-1 the
> fact that apply requires `dyn to resolve to nothing, but apply-1 allows
> `dyn to denote any pair-consed sequence of arguments?

No. The only difference between apply-1 and apply is that apply-1 always
expects a single argument to the function that is already in pair-cons'd
form. Because of this, apply-1 does not (in fact: cannot) check argument
arity agreement.

> >   5. In the presence of pair-consing, the presence of by-reference
> >      types becomes problematic. At the moment, by-ref is restricted to
> >      appear only in procedure argument types, and it is only safe there
> >      because we can presume a form of region-based safety that is
> >      guaranteed by the nature of the calling convention.
> > 
> 
> I think that the ref problem can be solved by requiring that the by-ref 
> arguments can only be implicitly pair-consed, not explicitly.

I think this is wrong. Contrast:

  (define (id-by-ref x (by-ref y) (pair x y))

with

  (define (id-by-ref arg:(pair x (by-ref y)) arg))

In the pair-consing view, these two ought to be the same, but they
aren't because by-ref is appearing inside a type constructor. What is
going to happen here is that the pair-consing implementation of the
compiler will, in effect, construct the second version from the first.

> That is, writing
> 
> (define (f (x : (by-ref int)  y:int)) <body>:int)
> 
> is legal, and f gets the type f:(((byref-int), int)) int)

In the pair-consing view, there is no such function type. The type must
be:

  f: (pair (by-ref int) int) -> int

which is not a legal type at the moment.

> All applications of f must be written in the form
> 
> (f x_actual 25)
> 
> It cannot be written as
> 
> (f (x_actual, 25)) since the argument to pair constructor is an rvalue 
> usage and will extract the value stored in x_actual.

Not so! Pair is a type constructor. In this case we will invoking the
concrete pair constructor whose type would be:

   construct-pair : (by-ref int) x int -> (pair (by-ref int) int)

[sorry about the reductio problem here in stating the type of the
concrete pair constructor]. Since the parameter type here is by-ref, it
is NOT the case that the argument to the constructor is an rvalue usage!


shap

_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to