Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No support for closures in lambdas ? #173

Closed
feedthejim opened this issue Jul 17, 2018 · 5 comments
Closed

No support for closures in lambdas ? #173

feedthejim opened this issue Jul 17, 2018 · 5 comments

Comments

@feedthejim
Copy link

Hi,

I'm trying to understand AssemblyScript by doing a little project. Is there no closure on lambdas ?

` trace(rayOrigin: Vector3, rayDirection: Vector3, depth: f64): Vector3 {
let tnear: f64 = Infinity;
let sphere: Sphere | null = null;

this.elements.forEach(
  (sphere: Sphere): void => {
    let hitInfo: Intersection | null = sphere.intersect(
      rayOrigin,
      rayDirection,
    );

`
This bit of code doesn't compile, it throws this error.

`ERROR TS2304: Cannot find name 'rayOrigin'.

       rayOrigin,
       ~~~~~~~~~

in assembly/RayTracer.ts(16,1`

Do i need to pass them as parameters to the lambda ?

@MaxGraey
Copy link
Member

MaxGraey commented Jul 17, 2018

Hi,
Inferring for closures has some limits for now, so if you want using functional methods your should declare full signature for closure like:

this.elements.forEach((sphere: Sphere, index: i32, array: Array<Sphere>): void => {
   ...
});

And I'm not sure about rayOrigin which should capture from lexical environment. @dcodeIO is it legit for now?

@dcodeIO
Copy link
Member

dcodeIO commented Jul 17, 2018

And I'm not sure about rayOrigin which should capture from lexical environment.

Can't capture yet. Reason is that closures like these usually need GC-support to attach an outer scope to the function being called, so if the inner function changes a value, the outer function sees the change as well. This is especially important for functions being assigned to values that can be called at any time, i.e. when the parent function already finished executing.

To work around this for now you could use a global variable that you assign the value to first, read the value from there in the inner function, and maybe set the updated value back in the parent function afterwards.

@MaxGraey
Copy link
Member

@dcodeIO Thanks!
I think better workaround for this current case switch from functional forEach to for (...) {}.

@dcodeIO
Copy link
Member

dcodeIO commented Jul 17, 2018

I think better workaround for this current case switch from functional forEach to for (...) {}.

This makes me think. One optimization we could theoretically do is to compile the forEach and its argument inline, allowing the inner function to access the parent scope. Would also eliminate the indirect call. Not sure how complicated that'd be, and it won't work in every case, but in this one here it should.

@feedthejim
Copy link
Author

Thanks for the quick answer guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants