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

Can receivers change return values? #25

Open
samuelgoto opened this issue Nov 30, 2017 · 3 comments
Open

Can receivers change return values? #25

samuelgoto opened this issue Nov 30, 2017 · 3 comments

Comments

@samuelgoto
Copy link
Owner

@ljharb's feedback:

Is it possible for receivers to change the value that gets returned? For example:

function a() {
  unless (false) {
    return 1;
  }
  return 2;
}

Is it possible, in any way, for unless to control what gets returned to a independently of what the block param returns lexically?

@ljharb
Copy link

ljharb commented Nov 30, 2017

(also @bmeck)

To clarify: is it possible in any way for unless to prevent return 2; from executing, short of invoking the block that contains return 1; lexically?

@samuelgoto
Copy link
Owner Author

It certainly feels awkward for unlesss to have the ability to return anything to a that wasn't written lexically inside of a in the block param.

Because receivers are written as functions in their own scope, there is nothing that they can do to change the return value of the functions. For example:

function unless(expr, block) {
  // I can store block, setTimeout on it, pass it around, etc. For example:
  // When executed, if block() returns, it throws a ContinuationException, 
  // something along the lines of this:
  // http://tronicek.blogspot.com/2008/08/nonlocal-transfer.html
  setTimeout(block);
  // returning 2 here doesn't return to the ```a``` function, but rather to the ```unlesss```
  // function.
  return 2;
}

It is interesting to note, though, that unless could use finally and throw an exception. For example:

function unless (expr, block) {
  try {
    block();
  } finally {
    throw 1;
  }
}

It is unclear to me what are the consequences of this and what are the possible solutions (e.g. swallowing exceptions? allowing?). Writing it down to make sure I don't forget what was discussed.

@bmeck
Copy link

bmeck commented Nov 30, 2017

We discussed an example of this at the meeting, with the assumption that the completion value slot is filled in a well defined way.

unless would write to a's completion value slot including with normal completions.

a would write to an implicit completion value and the above would roughly desugar to the following.

function a() {
  let a_completion = {
    type: 'normal',
    value: undefined
  };
  let block_completion = unless(false, () => {
    a_completion = {
      type: 'return',
      value: 1
    }
  });
  switch (a_completion.type) {
     case 'normal': break;
     case 'throw': throw a_completion.value;
     case 'return': return a_completion.value;
  }
}

Which would decouple non-exception values from changing the completion value of a. However, the question of if block_completion above would be able to overwrite a_completion for some types of completions. If so, which ones or why none.

I am not tied to any intent of the feature, but I feel like making some determination of pseudocode to be more concrete would make me able to more clearly discuss this.

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