# "static \<expr\>" syntax

**URL:** <https://es.discourse.group/t/static-expr-syntax/1673>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [April 4, 2023, 1:04pm UTC](https://es.discourse.group/t/static-expr-syntax/1673 "2023-04-04T13:04:59Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [April 4, 2023, 1:04pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/1 "2023-04-04T13:04:59Z")

</div>

# TL;DR

```js
function fn(){
  let a = static {x: 0}
  a.x++
  return a
}

console.assert(fn().x == 1)
console.assert(fn().x == 2)
console.assert(fn().x == 3)
const o = fn()
console.assert(fn() == fn() && fn() == o)
o.x = 99
console.assert(fn().x == 100)

```

Give additional functionality to the `static` keyword, to statically allocate an object  
I.e, the expression following the `static` keyword would only be evaluated once, and never again, even if it is found inside a function or loop. The `static` expression would then return the same value every time.

# Example use cases

### Consider the current solution to a hypothetical problem:

```js
const privateSymbol = Symbol('hidden')

function processObject(obj){
    if(obj[privateSymbol]) return obj[privateSymbol]
    //...
    // perform some processing
    //...
    obj[privateSymbol] = processedValue
    return processedValue
}

```

Despite this, `privateSymbol` remains exposed. We could create an IIFE or some other kind of closure,

```js
var processObject
{
    const privateSymbol = Symbol('hidden')

    processObject = function(obj){
        if(obj[privateSymbol]) return obj[privateSymbol]
        //...
        // perform some processing
        //...
        obj[privateSymbol] = processedValue
        return processedValue
    }
}

```

However, it would make more sense if we didn't have to define the symbol _outside_ the function

```js
function processObject(obj){
    const privateSymbol = Symbol('hidden')

    // .....
}

```

Unfortunately, now, our private symbol will be different with each call to the function.

In this proposal, the `static` keyword would be able to turn an expression inside a function (or loop, or anything else really) into a statically evaluted one,

```javascript
function processObject(obj){
    // This expression will evaluate to the same each time
    const privateSymbol = static Symbol('hidden')

    if(obj[privateSymbol]) return obj[privateSymbol]
    //...
    // perform some processing
    //...
    obj[privateSymbol] = processedValue
    return processedValue
}

```

# Other use cases

In react, it's not uncommon to declare styles inline, directly inside a component, e.g

```jsx
const MyComponent = () => {
    return <div style={ {color: 'red', fontSize: 30, cursor: 'pointer'} }>
        Hello!
    </div>
}

```

React would then have to parse the `style` object and turn it into a style declaration every time the component is rerendered, which is a lot of work, and it perhaps one of react's biggest performance downfall, especially noticable when using large complex apps like Discord

The `static` keyword would allow a cache-like optimization, where an object could be recognised, and would not require re-parsing, e.g

```js
function styleObjectToCss(obj){
  const cachedCss = static Symbol('cachedCss')

  // If the object has been seen before, use its cached value
  if(obj[cachedCss]) return obj[cachedCss]
  
  // Otherwise, perform expensive conversion
  const cssText = ...(obj)
  obj[cachedCss] = cssText
  return cssText
}

```

And our component would look like this

```jsx
const MyComponent = () => {
    return <div style={ static {color: 'red', fontSize: 30, cursor: 'pointer'} }>
        Hello!
    </div>
}

```

`static` would allow the same object to be passed each time, essentially allowing react to easily cache its css representation and only process our object once.

# Other use cases

There plenty other use cases that would be made simpler with the `static` keyword, here are a few examples:

- sha256 uses a precomputed table of fractional digits of `sqrt(2)`

- Functions can now be organized inside other functions without worrying about capturing or performance overhead (e.g when an exported function `thing` is a wrapper to the real function called `_thing`)

- Node uses objects as option parameters absolutely everywhere. Using static would allocate the object on the heap, but would only do so once during the entire duration of the program.

> **Important noteworthy point:** Since each static object is allocated _once_ only, it does not ever need to be garbage collected, meaning less memory and performance overhead for using that object

Unlike most other convenience feature, this feature provides a clear performance benefit over our current closest equivalent.

# Extensions

These are possible extensions to this proposal, feel free to suggest edits as I have not given deep thought to most of these.

### Native functions' return values

This subheading does not directly concern the `static` syntax, but rather the internal workings of native functions, that would likely be implemented in C++

Currently, `Generator#next()` returns a new object like `{value: any, done: boolean}`. This object is dynamically allocated and different every time. This object could be statically allocated with its values mutated every time, potentially increasing performance substantially (although I expect the difference would be less significant the more sophisticated the JS runtime is)  
Similarly, `Map` entry iterators return an array on each iteration. This array could also be statically allocated.

There are many other functions, native or not, that typically return dynamically allocated objects, such as `TextEncoder#encode()` or React's `useState`

### Static variable declaration

Best described by an example, this would work similarly to classes' `static`, and would be specific to each function, essentially inheriting its function's lifetime.

```js
function count(){
    static current = 0
    current++
    return current
}
console.assert(count() == 1)
console.assert(count() == 2)
console.assert(count() == 3)
console.assert(count.current == 3)

```

Let me know what you think!

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/senocular/32/642_2.png) [@senocular](https://es.discourse.group/u/senocular)\
**Post date:** [April 4, 2023, 3:39pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/2 "2023-04-04T15:39:56Z")

</div>

Related: [C-style static variables](https://es.discourse.group/t/c-style-static-variables/511)

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [April 4, 2023, 4:10pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/3 "2023-04-04T16:10:28Z")

</div>

Yeah, that idea seems pretty much identical to the second extension I defined. Not quite the same as my main proposal though.

The difference becomes clear when you imagine a function B declared inside a function A

**static variables** are attached to the function they are defined in, very comparable to classes' static variables. If a static variable is declared in function B, it is initialised when B is initialised (i.e every time A is called)

**static expressions** aren't attached to anything, they are program-wide. In our same scenario, it's still only evaluated once, ever. Calling A won't reinitialise it.

These 2, while fairly comparable, fundamentally solve different problems.

Additionally, that post has a comment suggesting a way we can achieve the same result currently, which I describe as (one of) the things this proposal aims to avoid.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 4, 2023, 11:14pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/4 "2023-04-04T23:14:13Z")

</div>

At what point does a static expression inside a function execute? The first time it's needed, or when the module first loads, or some other time?

This matters, because it effects what data the static expression is able to see. If they're being executed when the module first loads, then, well, they wouldn't be able to see any outside variables because no variables have been declared yet. If they execute the first time they're needed, then you risk the captured values becoming stale (which could be good or bad), e.g. if they use the function arguments to build an object, that object will forever contain the arguments that were there the first time the function ran.

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [April 5, 2023, 7:10am UTC](https://es.discourse.group/t/static-expr-syntax/1673/5 "2023-04-05T07:10:41Z")

</div>

I had given some thought to this, and decided they execute at the beginning of the current module. This does mean that they don't have access to variables defined in that module, but static expressions aren't really meant for indeterministic code (while still possible), but rather simple expressions like an object literal or a preallocated buffer. Accessing any other variables in that module or function scope would result in a ReferenceError ('cannot use this variable in this way etc...')

Another option I have considered is that they evaluate at the top-most-parent-function's initialization, but decided against it due to how CommonJS modules run on node, which may cause issues.

Let me know what you think. Are there any better time to execute static expressions? Did I miss something in my current approach?

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 5, 2023, 9:07pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/6 "2023-04-05T21:07:01Z")

</div>

They both have their trade-offs, so I don't know which I would prefer.

I do like the overall idea here. It would be nice to have a way to keep state specific to a function within that function.

I'm not sure how much traction a feature request like this would make though, since it's fairly trivial to work around the missing feature, but I still like it.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 22, 2024, 5:07am UTC](https://es.discourse.group/t/static-expr-syntax/1673/7 "2024-09-22T05:07:41Z")

</div>

If this `static` feature came out, then React would be able to implement Solid.js signals and effects to replace Hooks without changing its rendering execution model and catch up to Solid speed. 😃 😄 😁

```js
function MyReactComponent() {
  const [value, setValue] = static useSignal({ initial: 'value' })

  return ...
}

```

Maybe some global variable like `globalThis.isStaticExpression()` would be able to tell us if we're in a static expression (synchronous only), then React could just keep `useState` and the internal logic would know what to do:

```js
function MyReactComponent() {
  const [value, setValue] = static useHook({ initial: 'value' })

  return ...
}

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [September 22, 2024, 10:03am UTC](https://es.discourse.group/t/static-expr-syntax/1673/8 "2024-09-22T10:03:50Z")

</div>

If you're placing the static keyword at the location where the function returns a triple, doesn't that mean the tuple would be pre-calculated, and you'd always get the same tuple every time the function runs? Which means you'd always get the same value for the state?

I'm also not sure a static keyword would help React - React component functions can create multiple component instances, each of which need their own copy of state. A static keyword implies we would be sharing something among all component instances, which doesn't fit into what the hooks (or signals) do.

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [September 22, 2024, 10:28am UTC](https://es.discourse.group/t/static-expr-syntax/1673/9 "2024-09-22T10:28:57Z")

</div>

Returning a static triple doesn't make much sense (if one of the values is a plain object, you would place the static keyword there)  
Note that statics still have access to global and module variables, so they can be used as an alternative to initialising the tuple outside of the function and returning the same every time. If per-function is what you need and not per-module, then `static` variables is what you want, e.g

```js
const TopFunction = (x, y) => ({
  getSumAndProduct(){
    // Initialized at TopFunction()
    static pair = [x+y, x*y]
    return pair
  }
})

```

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 23, 2024, 5:15am UTC](https://es.discourse.group/t/static-expr-syntax/1673/10 "2024-09-23T05:15:38Z")

</div>

Ah, I underthought that a bit! 🤦‍♂️ Yeah, `static` won't help React because there's no way to make it static _per "instance"_ of a component, the expression could only be static for _all calls_ ever.

EDIT:

What if "cloning" a function would allow static expressions per _per clone_? For example something like the following (not sure "clone" is correct terminology):

```js
function foo() {
  const thing = static {}
  return thing 
}

const foo1 = foo.clone()
const foo2 = foo.clone()

console.log(foo1() === foo1()) // true
console.log(foo2() === foo2()) // true
console.log(foo1() === foo2()) // false

```

Then, React could clone function components (one time per component "instance") to make the `static` expressions actually useful.

```js
function MyComponent() {
  const [foo, setFoo] = static createSignal(123) // now this could work
}

```

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [September 23, 2024, 8:48am UTC](https://es.discourse.group/t/static-expr-syntax/1673/11 "2024-09-23T08:48:21Z")

</div>

the functionality you are describing is done with static variable declaration

```js
function MyComponent(){
  static [foo, setFoo] = createSignal(123)
}

```

As per the proposal I described, foo and setFoo would be specific to MyComponent. If MyComponent was defined inside another function, or as a class field, then it would be specific to each instance of that parent function invocation/class instance

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [September 23, 2024, 10:50am UTC](https://es.discourse.group/t/static-expr-syntax/1673/12 "2024-09-23T10:50:10Z")

</div>

What if you have multiple instances of `MyComponent`? Won't they share the static variable?

Regarding the OP "static expr", it's essentially unnamed global variables sprinkled throughout the code, and just like global variables, initialized even if never used. Where's the performance benefit? All I see is an attempt to dodge one of the most difficult problems in software engineering: naming.

I can't see a good use case here. Memoization is a pretty bad one for static expr or static variables. You're basically creating a distributed cache that's difficult to measure, update or prune. And no you're not making the symbol completely hidden. It's still accessible via `Object.getOwnPropertySymbols`.

> [@blob](#):
>
> - sha256 uses a precomputed table of fractional digits of `sqrt(2)`
> - Node uses objects as option parameters absolutely everywhere. Using static would allocate the object on the heap, but would only do so once during the entire duration of the program.

These would better be served with [records and tuples](https://github.com/tc39/proposal-record-tuple).

---

<div class="post-metadata">

**Author:** ![blob](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/blob/32/2230_2.png) [@blob](https://es.discourse.group/u/blob)\
**Post date:** [September 23, 2024, 12:19pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/13 "2024-09-23T12:19:46Z")

</div>

For the example above, multiple instances of MyComponent would have separate static variables, unlike multiple invocations which would share the same value.

Static expressions or variable declarations are not meant to replace global variables. They are meant to fill the gap where global variables make sense from a performance perspective but not from a readability perspective.

Static expressions are not meant to be used to implement memoization but to make it effective. Memoization is almost completely useless when given two similar objects with different identity (i.e {} != {}). One solution is the records proposal, however they do not perform nearly as well as static expressions would and would require changes to existing libraries whereas this would not. (Additionally consider that we would see potential improvements in more cases than just memoization)

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 23, 2024, 5:05pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/14 "2024-09-23T17:05:41Z")

</div>

> [@lightmare](#):
>
> initialized even if never used. Where's the performance benefit?

It could be initialized on first use.

---

<div class="post-metadata">

**Author:** ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)\
**Post date:** [September 23, 2024, 5:09pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/15 "2024-09-23T17:09:10Z")

</div>

> [@blob](#):
>
> For the example above, multiple instances of MyComponent would have separate static variables, unlike multiple invocations which would share the same value.

How could they have separate static variables, when there's still only one MyComponent function?

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 23, 2024, 5:17pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/16 "2024-09-23T17:17:22Z")

</div>

> [@blob](#):
>
> For the example above, multiple instances of MyComponent would have separate static variables, unlike multiple invocations which would share the same value.

The thing is, react calls the function multiple times per component instance (as many times as it needs to re-render), which is what @theScottyJam was reminding us.

If you have this component:

```js
function MyComponent ({count}) {
  ... static expression, or static variable, doesn't matter ...

  console.log("MyComponent", count)

  return ...template...
}

```

And then you use it like this:

```jsx
function OtherComponent() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    setInterval(() => setCount(count + 1), 1000)
  }, [])
  
  return <>
    <MyComponent count={count} />
    <MyComponent count={count} />
  </>
}

```

Then what will happen is every second the `MyComponent` function will be executed twice.

After 10 seconds `MyComponent` will have been called 22 times, logging "MyComponent" 22 times, but there are still only two "instances".

All 22 of those calls would share the single static expression or static variable.

OtherComponent will have been called 11 times if it was used in a single other JSX location.

There's no way to determine, purely from the function being called, how many "instances" React is tracking.

That's why I thought maybe that function "clone" idea would be interesting, to allow clones to create separate static context (on invocation, not ahead of time)

With the clone feature, React could clone a component per "instance".

* * *

On the other hand, [Solid.js](https://solidjs.com) runs a component function a single time per instance, so `static` expr or variable would be useful for shared state across all components (function clone idea would be pointless there)

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 23, 2024, 5:39pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/18 "2024-09-23T17:39:20Z")

</div>

@lightmare yeah we can use globals, but the nice thing about static is they are not globally exposed; they are lexically scoped despite global behavior.

might be nice to also specify which scope:

```js
function foo() {
  static module /*...*/; // effectively per source location 
  static outer /*...*/; // nearest scope around the function at execution
  static /*...*/; // defaults to one of the above
}

```

Compare:

```js
function creatFunc() {
  return function foo() {
    static module /*...*/; // shared static no matter how many of these functions are created
  }
}

```

vs

```js
function createFunc() {
  return function foo() {
    static outer /*...*/; // static per foo function based on each time it is created in scope of createFunc()
  }
}

```

where `foo.clone()` would always create a new function with a new static scope (in that case it doesn't matter which static scope the original had).

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [September 23, 2024, 10:07pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/19 "2024-09-23T22:07:21Z")

</div>

> [@trusktr](#):
>
> yeah we can use globals, but the nice thing about static is they are not globally exposed; they are lexically scoped despite global behavior

I don't see why module scopes, block scopes, or the occasional IIFE scope do not suffice for any of the mentioned use cases. A new `static` syntax doesn't bring that much benefit imo to warrant the introduction of new syntax.

Also, I really dislike global behavior that is hidden deep within code and not declared up front at the top level.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 23, 2024, 11:58pm UTC](https://es.discourse.group/t/static-expr-syntax/1673/20 "2024-09-23T23:58:50Z")

</div>

> [@bergus](#):
>
> I don't see why module scopes, block scopes, or the occasional IIFE scope do not suffice for any of the mentioned use cases

Of course those devices work. This is perhaps more about ergonomics and getting more joy writing.

We didn't really need `class` syntax, right? But it made expression better.

> [@bergus](#):
>
> dislike global behavior that is hidden deep within code and not declared up front at the top level.

Me too!

But this is different: the behavior is local to where it is defined, and does not affect outer scope in any way. You only read the static expression right at the location where it is defined, and it has no meaning outside of that location. The meaning is not shared with other code.

This,

```js
function foo() {
  return thing ?? static Object.freeze([])
}

```

Is potentially nicer to read and easier to write than this:

```js
export const defaultArray = Object.freeze([])

```

```js
import {defaultArray} from './consts.js'

function foo() {
  return thing ?? static Object.freeze([])
}

```

They are different: With `static`, the static value is available only to that specific source location, while the regular car is available to any code anywhere.

* * *

Just imagine a system like React though! It would be very unergonomic to hoist out all the expressions from all components that have them.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [September 24, 2024, 4:35am UTC](https://es.discourse.group/t/static-expr-syntax/1673/21 "2024-09-24T04:35:42Z")

</div>

> [@trusktr](#):
>
> This is perhaps more about ergonomics and getting more joy writing. We didn't really need `class` syntax, right? But it made expression better.

The difference is that `class`es are very common in JS code. I argue that `static` variables are not.

> [@trusktr](#):
>
> With `static`, the static value is available only to that specific source location, while the regular car is available to any code anywhere.

Why did you put the object in a separate module for no reason? I don't see much of a difference between

```js
export function foo() {
  return thing ?? static Object.freeze([]);
}

```

and

```js
const defaultArray = Object.freeze([]);
export function foo() {
  return thing ?? defaultArray;
}

```

[Next page](https://es.discourse.group/t/static-expr-syntax/1673.md?page=2)
