Skip to content

Commit

Permalink
[the-art] definePropagator -- handles currying
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyuheng committed Jun 10, 2024
1 parent 744e493 commit 6c2634b
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 30 deletions.
3 changes: 1 addition & 2 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# the-art

[the-art] `definePropagator` -- handles currying
[the-art] `heron.test.ts` -- use currying

[the-art] fix `definePrimitive`
[the-art] `examples/celsius/`

[the-art] 实现能够处理 interval 的 propagator
Expand Down
32 changes: 13 additions & 19 deletions src/the-art/propagator/definePrimitive.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { repeatApply } from "../../utils/repeatApply.js"
import {
addContent,
addPropagator,
broadcast,
content,
createCell,
type Cell,
} from "../cell/index.js"
import type { Propagator } from "./Propagator.js"
import { addContent, content, createCell, type Cell } from "../cell/index.js"
import { type PropagatorDefinitionWithFixedArity } from "./PropagatorDefinition.js"
import { watch } from "./watch.js"

// 我们知道所有的 primitive 都是函数,
// 因此如此构建的 propagator,
// 多个输入和一个输出。
// 因此所构建的 propagator 有多个输入和一个输出。
// 注意,这里的 arity 代表 propagator 的参数个数,
// 而不是函数的输入参数的个数。

// 作为浅嵌入,这里 `definePrimitive` 其实做的是:
// "create propagator constructor from native function"
// 因为真正的 propagator 类似 subscriber,
// 是可以不带参数就调用的 closure。
// 但是这个名字太长了,并且为了与深嵌入的 API 一致,
// 我们用了 define 这个前缀,因为深嵌入的 API 可能是:
// definePrimitive(mod, name, arity, fn)
// 另外 propagator definition 其实是 propagator constructor,
// 但是叫 definition 也没问题,并且能和深嵌入一致。

export function definePrimitive<A extends number>(
arity: A,
fn: (...args: Array<any>) => any,
Expand Down Expand Up @@ -66,14 +68,6 @@ export function definePrimitive<A extends number>(
return definition as unknown as PropagatorDefinitionWithFixedArity<A>
}

function watch(cells: Array<Cell<unknown>>, propagator: Propagator): void {
for (const cell of cells) {
addPropagator(cell, propagator)
}

broadcast([propagator])
}

function liftToCellContents(
fn: (...args: Array<any>) => any,
): (...args: Array<any>) => any {
Expand Down
33 changes: 24 additions & 9 deletions src/the-art/propagator/definePropagator.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
import type { Cell } from "../cell/index.js"
import type { PropagatorDefinition } from "./PropagatorDefinition.js"
import { repeatApply } from "../../utils/repeatApply.js"
import { createCell, type Cell } from "../cell/index.js"
import type { PropagatorDefinitionWithFixedArity } from "./PropagatorDefinition.js"

export function definePropagator(
arity: number,
export function definePropagator<A extends number>(
arity: A,
fn: (...args: Array<Cell<unknown>>) => void,
): PropagatorDefinition {
const definiton = (...args: Array<Cell<unknown>>) => {
fn(...args)
): PropagatorDefinitionWithFixedArity<A> {
const definition = (...args: Array<Cell<unknown>>) => {
if (args.length === arity) {
fn(...args)
} else if (args.length === arity - 1) {
const output = createCell()
fn(...args, output)
return output
} else if (args.length < arity - 1) {
const outputs = repeatApply(arity - args.length, () => createCell(), [])
fn(...args, ...outputs)
return outputs
} else {
throw new Error(
`[definePropagator] number of arguments ${args.length} exceed arity plus one: ${arity + 1}`,
)
}
}

definiton.arity = arity
definition.arity = arity

return definiton
return definition as unknown as PropagatorDefinitionWithFixedArity<A>
}
13 changes: 13 additions & 0 deletions src/the-art/propagator/watch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { addPropagator, broadcast, type Cell } from "../cell/index.js"
import type { Propagator } from "./Propagator.js"

export function watch(
cells: Array<Cell<unknown>>,
propagator: Propagator,
): void {
for (const cell of cells) {
addPropagator(cell, propagator)
}

broadcast([propagator])
}

0 comments on commit 6c2634b

Please sign in to comment.