Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions text/1071-cell.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ interface Cell<Value> extends Reactive<Value> {
/**
* Utility to create a Cell without the caller using the `new` keyword.
*/
static create<T>(initialValue: T, equals?: (a: T, b: T) => boolean): Cell<T>;
Copy link
Copy Markdown

@lifeart lifeart Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we support lazy values?
For example, if initial value is a tricky logic, there is no reason to resolve it during cell creation, because it may be used later.

// a-lot of compute
const value = new Array(10000).fill(null);
const arrays = Cell.create(value);

// lazy, no compute 
const value = () => new Array(10000).fill(null);
const arrays = Cell.createLazy(value);

(case for decorators too, where initializer is a may be reactive value, and we may be "looped")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would the implementation of createLazy potentially look like?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this: https://github.com/lifeart/glimmer-next/blob/master/src/utils/reactive.ts#L142 it's not 100% accurate, but main idea is same

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't dynamically created/modified objects create extra memory pressure?

Copy link
Copy Markdown

@lifeart lifeart Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NullVoxPopuli it is, but it depends on usecase, in browser we limited by CPU, not by memory :)

also, it may be a case where we create value, but it's not used (set is called before get) and in this case we saving alot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why it couldn't be added later as well

It may make more sense to do lazy construction in objects/arrays/maps, etc?

static create<T>(initialValue: T, equals?: (a: T, b: T) => boolean, description?: string): Cell<T>;
Comment thread
NullVoxPopuli marked this conversation as resolved.
Outdated

/**
* The constructor takes an optional initial value and optional equals function.
Expand Down Expand Up @@ -113,25 +113,34 @@ interface Cell<Value> extends Reactive<Value> {
Behaviorally, the `Cell` behaves almost the same as this function:
```js
class CellPolyfill {
@tracked current;
#isFrozen = false;
#value;

constructor(initialValue) {
this.current = initialValue;
constructor(initialValue, equals, description) {
this.#value = initialValue;
// ...
}

get current() {
// + consume
return this.#value;
}

read() {
return this.current;
// + consume
return this.#value;
}

set(value) {
assert(`Cannot set a frozen Cell`, !this.#isFrozen);
this.current = value;
// + dirty
this.#value = value;
}

update(updater) {
assert(`Cannot update a frozen Cell`, !this.#isFrozen);
this.set(updater(this.read()));
// #value is not tracked
this.set(updater(this.#value));
}

freeze() {
Expand Down Expand Up @@ -227,7 +236,7 @@ function tracked(target, key, { initializer }) {
let cell = cells.get(obj);

if (cell === undefined) {
cell = Cell.create(initializer.call(this), () => false);
cell = Cell.create(initializer.call(this), null, `tracked:${key}`);
cells.set(this, cell);
}

Expand Down Expand Up @@ -264,7 +273,7 @@ export function tracked(target, context) {
},

init(value) {
return Cell.create(value);
return Cell.create(value, null, `tracked:${key}`);
},
};
}
Expand Down