@@ -154,7 +154,33 @@ object Signal:
154
154
@ implicitNotFound(missingCanEqual)
155
155
canEqual : CanEqual [A , A ]
156
156
): Ref [A ] < IO =
157
- IO .Unsafe (new Ref (Ref .Unsafe .init(initial)))
157
+ initRefWith[A ](initial)(identity)
158
+
159
+ /** Creates a new mutable signal reference with an initial value and applies a transformation function.
160
+ *
161
+ * This method initializes a new `Signal.Ref[A]` that can be modified over time, and immediately applies a transformation function to
162
+ * it. The reference starts with the provided initial value and the transformation is applied within the same atomic operation.
163
+ *
164
+ * @param initial
165
+ * The starting value for the signal reference
166
+ * @param f
167
+ * The transformation function to apply to the newly created reference
168
+ * @return
169
+ * The result of applying the transformation function
170
+ * @tparam A
171
+ * The type of value contained in the signal. Must have an instance of `CanEqual[A, A]`
172
+ * @tparam B
173
+ * The return type of the transformation function
174
+ * @tparam S
175
+ * The effect type of the transformation function
176
+ */
177
+ def initRefWith [A ](initial : A )[B , S ](f : Ref [A ] => B < S )(
178
+ using
179
+ frame : Frame ,
180
+ @ implicitNotFound(missingCanEqual)
181
+ canEqual : CanEqual [A , A ]
182
+ ): B < (S & IO ) =
183
+ IO .Unsafe (f(new Ref (Ref .Unsafe .init(initial))))
158
184
159
185
/** Creates a new immutable signal with a constant value.
160
186
*
@@ -179,6 +205,32 @@ object Signal:
179
205
nextWith = [B , S ] => f => f(value)
180
206
)
181
207
208
+ /** Creates a new immutable signal with a constant value and applies a transformation function.
209
+ *
210
+ * This method creates a signal that always returns the same value and immediately applies a transformation function to it. Unlike
211
+ * `Signal.Ref`, this signal cannot be modified after creation.
212
+ *
213
+ * @param value
214
+ * The constant value for the signal
215
+ * @param f
216
+ * The transformation function to apply to the newly created signal
217
+ * @return
218
+ * The result of applying the transformation function
219
+ * @tparam A
220
+ * The type of value contained in the signal. Must have an instance of `CanEqual[A, A]`
221
+ * @tparam B
222
+ * The return type of the transformation function
223
+ * @tparam S
224
+ * The effect type of the transformation function
225
+ */
226
+ def initConstWith [A ](value : A )[B , S ](f : Signal [A ] => B < S )(
227
+ using
228
+ frame : Frame ,
229
+ @ implicitNotFound(missingCanEqual)
230
+ canEqual : CanEqual [A , A ]
231
+ ): B < S =
232
+ f(initConst(value))
233
+
182
234
/** Creates a new signal by specifying its fundamental operations.
183
235
*
184
236
* This is a lower-level constructor that allows direct implementation of a signal's behavior through its currentWith and nextWith
@@ -205,6 +257,39 @@ object Signal:
205
257
): Signal [A ] =
206
258
_initRaw(currentWith, nextWith)
207
259
260
+ /** Creates a new signal by specifying its fundamental operations and applies a transformation function.
261
+ *
262
+ * This is a lower-level constructor that allows direct implementation of a signal's behavior through its currentWith and nextWith
263
+ * operations, and immediately applies a transformation function to the created signal. It's primarily intended for implementing signal
264
+ * combinators and custom signal types.
265
+ *
266
+ * @param currentWith
267
+ * The implementation of currentWith, handling synchronous value access and transformation
268
+ * @param nextWith
269
+ * The implementation of nextWith, handling asynchronous value changes and transformation
270
+ * @param f
271
+ * The transformation function to apply to the newly created signal
272
+ * @tparam A
273
+ * The type of value contained in the signal. Must have an instance of `CanEqual[A, A]`
274
+ * @tparam B
275
+ * The return type of the transformation function
276
+ * @tparam S
277
+ * The effect type of the transformation function
278
+ * @return
279
+ * The result of applying the transformation function
280
+ */
281
+ @ nowarn(" msg=anonymous" )
282
+ inline def initRawWith [A ](
283
+ inline currentWith : [B , S ] => (A => B < S ) => B < (S & IO ),
284
+ inline nextWith : [B , S ] => (A => B < S ) => B < (S & Async )
285
+ )[B , S ](f : Signal [A ] => B < S )(
286
+ using
287
+ frame : Frame ,
288
+ @ implicitNotFound(missingCanEqual)
289
+ canEqual : CanEqual [A , A ]
290
+ ): B < S =
291
+ f(initRaw(currentWith, nextWith))
292
+
208
293
// Separated from initRaw to avoid name conflicts between parameters and Signal members
209
294
@ nowarn(" msg=anonymous" )
210
295
private inline def _initRaw [A ](
@@ -244,7 +329,19 @@ object Signal:
244
329
* @return
245
330
* The current value
246
331
*/
247
- def get (using Frame ): A < IO = IO .Unsafe (_unsafe.get())
332
+ def get (using Frame ): A < IO = use(identity)
333
+
334
+ /** Retrieves and transforms the current value of the reference.
335
+ *
336
+ * This is a convenience method that provides synchronous access to the reference's current value while applying a transformation
337
+ * function. It's equivalent to `currentWith` but with a more familiar name for reference types.
338
+ *
339
+ * @param f
340
+ * The transformation function to apply to the current value
341
+ * @return
342
+ * The transformed value wrapped in combined effects S & IO
343
+ */
344
+ inline def use [B , S ](inline f : A => B < S )(using Frame ): B < (S & IO ) = IO .Unsafe (f(_unsafe.get()))
248
345
249
346
/** Sets the reference to a new value.
250
347
*
0 commit comments