259 lines
5.6 KiB
TypeScript
Executable File
259 lines
5.6 KiB
TypeScript
Executable File
/**
|
|
* @since 2.0.0
|
|
*/
|
|
import * as Equal from "./Equal.js"
|
|
import * as Dual from "./Function.js"
|
|
import { format, type Inspectable, NodeInspectSymbol, toJSON } from "./Inspectable.js"
|
|
import type { Pipeable } from "./Pipeable.js"
|
|
import { pipeArguments } from "./Pipeable.js"
|
|
|
|
const TypeId: unique symbol = Symbol.for("effect/MutableRef") as TypeId
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category symbol
|
|
*/
|
|
export type TypeId = typeof TypeId
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category models
|
|
*/
|
|
export interface MutableRef<out T> extends Pipeable, Inspectable {
|
|
readonly [TypeId]: TypeId
|
|
current: T
|
|
}
|
|
|
|
const MutableRefProto: Omit<MutableRef<unknown>, "current"> = {
|
|
[TypeId]: TypeId,
|
|
toString<A>(this: MutableRef<A>): string {
|
|
return format(this.toJSON())
|
|
},
|
|
toJSON<A>(this: MutableRef<A>) {
|
|
return {
|
|
_id: "MutableRef",
|
|
current: toJSON(this.current)
|
|
}
|
|
},
|
|
[NodeInspectSymbol]() {
|
|
return this.toJSON()
|
|
},
|
|
pipe() {
|
|
return pipeArguments(this, arguments)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category constructors
|
|
*/
|
|
export const make = <T>(value: T): MutableRef<T> => {
|
|
const ref = Object.create(MutableRefProto)
|
|
ref.current = value
|
|
return ref
|
|
}
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const compareAndSet: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(oldValue: T, newValue: T): (self: MutableRef<T>) => boolean
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, oldValue: T, newValue: T): boolean
|
|
} = Dual.dual<
|
|
<T>(oldValue: T, newValue: T) => (self: MutableRef<T>) => boolean,
|
|
<T>(self: MutableRef<T>, oldValue: T, newValue: T) => boolean
|
|
>(3, (self, oldValue, newValue) => {
|
|
if (Equal.equals(oldValue, self.current)) {
|
|
self.current = newValue
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const decrement = (self: MutableRef<number>): MutableRef<number> => update(self, (n) => n - 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const decrementAndGet = (self: MutableRef<number>): number => updateAndGet(self, (n) => n - 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const get = <T>(self: MutableRef<T>): T => self.current
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const getAndDecrement = (self: MutableRef<number>): number => getAndUpdate(self, (n) => n - 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const getAndIncrement = (self: MutableRef<number>): number => getAndUpdate(self, (n) => n + 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const getAndSet: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(value: T): (self: MutableRef<T>) => T
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, value: T): T
|
|
} = Dual.dual<
|
|
<T>(value: T) => (self: MutableRef<T>) => T,
|
|
<T>(self: MutableRef<T>, value: T) => T
|
|
>(2, (self, value) => {
|
|
const ret = self.current
|
|
self.current = value
|
|
return ret
|
|
})
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const getAndUpdate: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(f: (value: T) => T): (self: MutableRef<T>) => T
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, f: (value: T) => T): T
|
|
} = Dual.dual<
|
|
<T>(f: (value: T) => T) => (self: MutableRef<T>) => T,
|
|
<T>(self: MutableRef<T>, f: (value: T) => T) => T
|
|
>(2, (self, f) => getAndSet(self, f(get(self))))
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const increment = (self: MutableRef<number>): MutableRef<number> => update(self, (n) => n + 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category numeric
|
|
*/
|
|
export const incrementAndGet = (self: MutableRef<number>): number => updateAndGet(self, (n) => n + 1)
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const set: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(value: T): (self: MutableRef<T>) => MutableRef<T>
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, value: T): MutableRef<T>
|
|
} = Dual.dual<
|
|
<T>(value: T) => (self: MutableRef<T>) => MutableRef<T>,
|
|
<T>(self: MutableRef<T>, value: T) => MutableRef<T>
|
|
>(2, (self, value) => {
|
|
self.current = value
|
|
return self
|
|
})
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const setAndGet: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(value: T): (self: MutableRef<T>) => T
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, value: T): T
|
|
} = Dual.dual<
|
|
<T>(value: T) => (self: MutableRef<T>) => T,
|
|
<T>(self: MutableRef<T>, value: T) => T
|
|
>(2, (self, value) => {
|
|
self.current = value
|
|
return self.current
|
|
})
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const update: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(f: (value: T) => T): (self: MutableRef<T>) => MutableRef<T>
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, f: (value: T) => T): MutableRef<T>
|
|
} = Dual.dual<
|
|
<T>(f: (value: T) => T) => (self: MutableRef<T>) => MutableRef<T>,
|
|
<T>(self: MutableRef<T>, f: (value: T) => T) => MutableRef<T>
|
|
>(2, (self, f) => set(self, f(get(self))))
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
export const updateAndGet: {
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(f: (value: T) => T): (self: MutableRef<T>) => T
|
|
/**
|
|
* @since 2.0.0
|
|
* @category general
|
|
*/
|
|
<T>(self: MutableRef<T>, f: (value: T) => T): T
|
|
} = Dual.dual<
|
|
<T>(f: (value: T) => T) => (self: MutableRef<T>) => T,
|
|
<T>(self: MutableRef<T>, f: (value: T) => T) => T
|
|
>(2, (self, f) => setAndGet(self, f(get(self))))
|
|
|
|
/**
|
|
* @since 2.0.0
|
|
* @category boolean
|
|
*/
|
|
export const toggle = (self: MutableRef<boolean>): MutableRef<boolean> => update(self, (_) => !_)
|