def add_x x = lambda y = x + y
x : 'a -> ('a -> 'a)

def add_one = add_x 1

I don't see the problem. "add_one" is a stack allocated object in the top
level context. First we reserve the space for the closure on the stack
(labeled add_one). Then we pass this to add_x, which gets the closure to
mutate and 1 as the value. We define x and the return function inside the
'add_one' object which is stack allocated before the add_x function
stack-frame. when add_x returns we are left with the 'add_one' closure on
the top of the stack. This is an object that contains the value of y, and
the function 'add_one'.

Keean.





On 11 February 2015 at 17:34, Jonathan S. Shapiro <[email protected]> wrote:

> On Wed, Feb 11, 2015 at 8:53 AM, Keean Schupke <[email protected]> wrote:
>
>> I have an idea that closures can (always?) be stack allocated...
>>
>
> Counter-example:
>
> def add_x x = lambda y = x + y
> x : 'a -> ('a -> 'a)
>
> def add_one = add_x 1
>
> The closure captured by the lambda is necessarily heap allocated.  What
> *is* true, however, is that you can put a region on the procedure formation
> and infer the cases where the closure *can* be stack allocated. Basically
> this converts my earlier "does not escape" constraint to "does not
> constraint region 'r".
>
> In regards to currying, without partial application, all currying does is
>> introduce inefficiency as you have to accumulate all the arguments
>> somewhere before calling the function. I think in the non-partial
>> application case un-curried functions make more sense.
>>
>
> I think we agree. The main reason to want arity on the type is so that we
> know what's supposed to occur at separate compilation boundaries. But it
> does introduce some unfortunate questions about type compatibility.
>
>
>> The problem with partial evaluation is, consider:
>>
>> f x y = (g x) + (h y)
>>
>> What if 'g' throws a division by zero error, or runs out of memory and
>> throws a runtime exception. In that case with partial evaluation, the
>> program will fail as soon as 'f' is applied to its first argument....
>>
>
> I agree. I was confusing "partial evaluation" with "partial application".
> Though now that I think about it, the term "partial application" already
> assumes arity-sensitive application.
>
> Two comments here:
>
> 1. Partial evaluation isn't necessarily an optimization. It's only an
> optimization when we know that evaluation will (eventually) occur.
> 2. When we do *not* know that evaluation will occur, partial evaluation
> is *incorrect* if it alters the delivery of errors.
>
> Your example above is actually pretty interesting, because it reveals the
> first case I have seen where exception objects want to be first-class. If
> (g x) raises an exception E, it would be perfectly fine to partially
> evaluate this to
>
>   lambda y = raise E
>
> but that only works of the exception raised can be statically determined.
> When it can't, then either we need first-class exception values or we can't
> do the partial evaluation this way.
>
>
>> In the extreme case where the computation is abandoned before the second
>> argument is applied this could be the difference between the program
>> crashing, and running with no errors. So its not Laziness thats the only
>> problem, partial evaluation is too, and without partial evaluation, what is
>> the point of currying? All it does is make things less efficient.
>>
>
> I think the re-write that I just gave preserves the argument evaluation
> guarantee.
>
>
> shap
>
>
> _______________________________________________
> bitc-dev mailing list
> [email protected]
> http://www.coyotos.org/mailman/listinfo/bitc-dev
>
>
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to