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

Decorators for assignment expressions? const/let declarations? #51

Open
littledan opened this issue Feb 10, 2018 · 4 comments
Open

Decorators for assignment expressions? const/let declarations? #51

littledan opened this issue Feb 10, 2018 · 4 comments

Comments

@littledan
Copy link
Member

Previous discussion: tc39/proposal-decorators-previous#32

OK to leave as a follow-on proposal?

@mikesamuel
Copy link
Member

Use case: runtime guards

This came up at es-discuss "Proposal to add symbol: hasInstanceStrict" that

attempts to provide an intermediate layer for implementing runtime type checking.

to which TJCrowser replied

When [decorators][1] land, provided they land with a means of [decorating
functions][2] (either as part of that proposal or as a follow-on), that
would do the job, wouldn't it?

The response was that decorators do not allow vetting a value assigned to a local as in

const c: PrimitiveNumber = sum(1, 2);

This issue came up later on:

It seems that there are two separable issues:

  1. Defining guards
  2. Syntax for specifying guards.

It seems to me that (2) might be doable with annotations decorators for locals,
so deploying guards could build on annotations decorators.

@MrEfrem
Copy link

MrEfrem commented Feb 21, 2018

Propose to use such syntax:

@primitiveNumber const c = sum(1, 2);

@bmeck
Copy link
Member

bmeck commented Feb 28, 2018

I'd prefer to leave it as a follow on.

@lightmare
Copy link

lightmare commented Jun 30, 2021

I'd like to suggest changing the const decorators extension to include a get. The way it's currently proposed, it's nothing but syntax sugar for a function call, and is inconsistent with the let variant. Changing a variable declaration from let to const shouldn't change the behaviour of reads (provided the decorator supports read-only operation). Such as the example let @deprecated x = 1, should work the same for const @deprecated y = 1.

With a getter on const, you could do lazy evaluation:

const @lazy maybeNeeded = () => calc(...args);
if (day === "Sunday") { result += f(maybeNeeded); }
if (month === "June") { result += g(maybeNeeded); }
function lazy({ get, set, value }, { kind }) {
  let ready = false;
  switch (kind) {
    case "const": return { get: getLazy, value };
    case "let": return { get: getLazy, set: setLazy, value };
    default: throw Error("bad kind");
  }
  function getLazy() {
    if (!ready) value = get()(), ready = true;
    return value;
  }
  function setLazy(v) {
    set(v);
    ready = false;
  }
}

On another note, can the whole semantics of the { get, set, value } parameter be changed? I don't quite understand the rationale behind allowing the decorator to change the value that's eventually stored in the backing variable. This value travels through decorator chain in the opposite direction than the v in set(v) does, which means you cannot compose decorators that do transformation on assignment.

I would instead suggest { get, set }, where both are single-argument functions returning the transformed value.

// add +1 when reading
function lazyInc({ get, set }) { return { get: v => get(v) + 1, set }; }

// add +1 on initialization and assignment
function eagerInc({ get, set }) { return { get, set: v => set(v + 1) }; }

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

5 participants