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

Explicit this parameter #84

Closed
71104 opened this issue May 22, 2016 · 6 comments
Closed

Explicit this parameter #84

71104 opened this issue May 22, 2016 · 6 comments

Comments

@71104
Copy link
Owner

71104 commented May 22, 2016

The main use case for lazy values is no-arg methods. No-arg methods actually have an argument, which is this. Expliciting that argument will allow for removal of lazy values, with immense advantages in terms of simplified implementation. It will also allow users to implement their own no-arg methods, which is currently impossible because there is no syntax to define lazy values.

Syntax example:

let Box = fix fn Box, s ->
  let this.value = parseInt s 10,
    this.next = fn this ->
      new Box (this.value + 1) in this
in

console.log (new Box "5").next.next.value  # prints 7

This is quite easy to fix using the following steps:

  1. make this a regular identifier rather than a keyword;
  2. make the field access operator bind the first parameter if the accessed field is a closure;
  3. remove lazy values.

Note that this actually makes it possible to call this with an arbitrary name. E.g.:

let Box = fix fn Box, s ->
  let this.value = parseInt s 10,
    this.next = fn self ->
      new Box (self.value + 1) in this
in

console.log (new Box "5").next.next.value  # prints 7

This is not necessarily bad.

@71104
Copy link
Owner Author

71104 commented Jun 6, 2016

A first implementation is provided in this.

Problems:

  1. console.log has length 0 in Node v4.4.3, therefore it is no longer possible to log anything to the console.
  2. All operators now marshal to native functions that expect the first operand in this. This is extremely bad because it's totally unexpected by an average user and it is also incompatible with the current implementation of List's prototype. E.g., {1, 2, 3}.max <= fails miserably.

@71104
Copy link
Owner Author

71104 commented Jun 6, 2016

Possible solution for problem 2: make this a keyword again and marshal "implicitly" any parameter whose name is "this".

Example marshals:

  • fn x -> ...function (x) { ...
  • fn x, y -> ...function (x, y) { ...
  • fn this -> ...function () { ...
  • fn this, x -> ...function (x) { ...
  • fn this, x, y -> ...function (x, y) { ...
  • fn x, this, y -> ...function (x) { return function (y) { ...
  • fn x, this -> ...function (x) { return function () { ...

@71104
Copy link
Owner Author

71104 commented Jun 6, 2016

To solve problem 1, c0cf75b forces the arity of native functions to at least 2. This causes problems with methods of default prototypes, which are currently implemented as native nodes. For example, the reverse method of lists now has arity 1 after being bound to this, and, as a result, the following:

{1, 2, 3}.reverse

returns a closure instead of {3, 2, 1}. Applying a further dummy argument works:

{1, 2, 3}.reverse 0  # yields {3, 2, 1}

but it's definitely not intended.

Default prototypes need to be reimplemented as semi-native nodes. This will also provide performance improvements as values won't have to be marshalled every time one of those methods is invoked.

@71104
Copy link
Owner Author

71104 commented Jun 16, 2016

bindThis also needs to be implemented for types and invoked by FieldAccessNode.getType.

71104 added a commit that referenced this issue Jun 17, 2016
71104 added a commit that referenced this issue Jun 17, 2016
@71104 71104 closed this as completed in 7bf9613 Jun 17, 2016
@71104
Copy link
Owner Author

71104 commented Jun 19, 2016

Reopening due to undesired side-effect:

Math.pow.length                             # 2

let Math.lol = Math.pow in Math.lol.length  # 1

let Math.lol = Math.pow in Math.lol 2       # 0

let Math.lol = Math.pow in Math.lol 2 3     # runtime error

@71104 71104 reopened this Jun 19, 2016
@71104
Copy link
Owner Author

71104 commented Jun 19, 2016

This is actually intended, by design; and it would also behave like that with Lambda objects/methods. The field access operator binds the first argument of the method, so its arity is decreased by 1. I guess I have to get used to it.

@71104 71104 closed this as completed Jun 19, 2016
@71104 71104 mentioned this issue Jun 19, 2016
71104 added a commit that referenced this issue Jun 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant