Halting problem
# intro
今天摸鱼的时候突然看到了发布订阅,于是想着来写一个。不料突然在怎么取消订阅的一步卡壳了【想成写一个逻辑去判断是否两个函数相等,相等就取消,这里傻了,直接判断是否是自己就可以,因为这里是引用】,于是我就神奇的搜了一下判断函数相等的问题。
然后,发现了新大陆!
函数是否相等其实可变为相似的**停机问题 (opens new window)**
那么我们能不能有这样一个函数等于已知函数 FOO 呢?
换句话说,我们能不能写一个方法,返回一个函数等于 FOO 呢
定义一个函数 F ,对于任何函数,可以判断它返回值是否等于一个已知函数 FOO
function F(func):boolean {
return func === FOO
}
1
2
3
2
3
定义一个捣蛋函数 C
function C(m)=>{
if(f(m) === true) return null
if(f(m) === false) return FOO
}
// 从 F 函数定义出发
F(C) = true => C(X:any) === FOO
// 从 C 函数出发
C(C) => f(C) === true C(C) === null
C(C) => f(C) === false C(C) === FOO
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
所以看到,这里无论 f(C) 等于什么,最后都会和其本身的定义相矛盾
所以不存在一个能判断函数是否相等的函数。扩展开来,编程不是万能的。
其实里面的问题就在于定义是一个全局的,不分先后的。但是如果利用它自己的结果来再次定义返回就会被钻篓子。
# 最后补一个简单的发布订阅
function typeCheck(type) {
if (!typeof type === 'string' && type !== '') {
console.error('type must be non-empty string')
return
}
}
class Notify {
constructor() {
this.event = {}
}
emit(type, data) {
typeCheck(type)
const _event = this.event
_event[type].map(fn => fn(data))
}
on(type, callback) {
typeCheck(type)
const _event = this.event
if (!Array.isArray(_event[type])) _event[type] = [callback]
else _event[type].push(callback)
}
off(type, callback) {
typeCheck(type)
const _event = this.event
if (!Array.isArray(_event[type])) return
const index = _event[type].findIndex(fn => fn !== callback)
_event[type].splice(index, 1)
}
once(type, callback) {
this.on(type, data => {
callback(data)
this.off(type, callback)
})
}
}
const notify = new Notify()
function handle(msg) {
console.log('msg', msg)
}
notify.once('msg', handle)
notify.emit('msg', 'hi~')
notify.emit('msg', 'hi123~')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53