github.com/rainforesters/imsure 一直在用,确实好用,已经离不开了
github.com/rainforesters/imsure-demo
上周发了一个主题后评论区颇为热闹,就用此文统一回复下吧。我不想争论是非,只是我觉得这个理论就像日心说一样值得被更多人知道,应该被更多人知道,哪怕它和日心说一样被证明是错的,也算挣脱了思维桎梏,启迪了方向。若值得在茶饭之余引发讨论就更好了。

程序的本质是数据转换,那么逻辑过程的意义可以一概视为根据 input 转换为 output ,所以我们可以试着改变一下程序的编写方式,
从:

f(input) ⇒ output

进化为:

output ⇐ Watch_transform(input)
Rule = Watch_transform
output ⇐ Rule(input)

为了让观察转换变得可行,我们把 input output 作为字段都定义在抽象的 Struct 类型上,
那么就得到了:

self.output ⇐ Rule(Struct.input)
self 是 Struct 的实例
Rule 就可以在 self 未实例化之前,提前定义在抽象的 Struct 类型上;同时也允许 input output 在 Struct 的不同层级

这就变为了纯粹的数据转换链。只要依赖的 input 更新 output 也会随之更新,整条链也随之更新到最终稳定状态,既简单又保证了确定性。在转换链中,每个节点只干一件事,只需观察依赖的前置数据而不必考虑后续自己会驱动谁或被谁所依赖,彻底摆脱逻辑控制流。
这种写法就像从算术方法到方程解法一样具有普适性。
从传统编程需要根据不同业务需求设计不同的实现过程,到全然不用设计,只套用一条普适的方法就行:

定义数据结构。(设未知数)
定义转换规则。(列方程式)
为字段赋值。(代入已知数)

至此,就再也不需要推导业务逻辑了。

若你看懂了以上内容,那这段自不必说,若没看懂请继续。
传统逻辑过程可以细分为两部分:

先把将要进行转换的 input output 建立关联。
然后进行转换,纯粹的转换算法。

传统写法下 80% - 90% 的代码都在建立关联、维护关联,其实转换算法的代码很少很少。
新写法中建立关联就像呼吸一样简单。

"告别不会写,菜鸟变老鸟,老鸟变鲲鹏,自己写的代码一定是对的,没有 bug 。"
拉黑不送

感觉像程序逻辑之外再隐藏一个巨大的状态机,属于那种加一行炸了死活找不到原因的。

找韭菜不建议来这里找,
作为卖课人首先要学会找准潜在目标客户。

什么东西?对面向对象概念有了解的,或者懂些 DDD 的 coder ,会同意你拿这些皮毛来割韭菜吗?
建议大家看看什么才是真正的知识分享: docs.mryqr.com/build-your-own-software-skyscraper/

引用一下你的发言:

这个理论就像日心说一样值得被更多人知道,应该被更多人知道,哪怕它和日心说一样被证明是错的,也算挣脱了思维桎梏,启迪了方向

感觉可以了解一下 邓宁-克鲁格效应。

如果都按照这个思想去训练大模型,你猜会出来什么。

你说的这些在学术领域专门用来做数据分析、不放生产环境的语言里并不少见,例如 R
但结论就是业界基本没人用

你这个有没有应用到复杂度高一点的实际项目中的例子

说实话,我没看懂

看到了数据转换,难道是 rjava 那种数据驱动的思想?

怕你不服气,我抽了点时间看了看这个的几页介绍才来回复的。
首先,这种方式并没有真正消除逻辑复杂性,而是将其分散到各个独立的 ruledef 里。debug 的时候就知道什么是 callback hell 了。
然后,对于需要显式控制执行顺序、循环次数、中断条件等的场景,用这个方式反而是徒增思考成本。
还有,用 setTimeout 解决递归问题的行为,太变态了无法评价。

我举两个例子:
dijkstra 算法和需要 rollback 的时候,用你这个所谓的“挣脱了思维桎梏,启迪了方向”的编程思想,都是依托答辩。

函数式编程?

#10 我也是看到那句“巧妙地借助 setTimeout 来放空当前堆栈,在下一个调用帧来修正自己”,大为震撼,不能说这里有什么 bug ,但根据经验来看,这地方铁定有坑,而且很难排查。

忍不住回复下,看到这里大为震撼,缓缓打出一个?

由于结构体都是开放的、纯粹的,所以无法在赋值时进行拦截。不过我们可以通过定义一个规则来观察某个字段并修正自己。这就导致了递归,因为递归可能会导致堆栈溢出,所以我们巧妙地借助 setTimeout 来放空当前堆栈,在下一个调用帧来修正自己。

写的什么八股文,代码是给人看的

鉴定为魔道学者

我学不学无所谓,面向对象必须死!

本不想评论,但既然都在说递归,那么就简单解释一下吧,禁用递归是刻意为之,而不是不能实现,允许递归其实更容易实现。那么禁用递归的主要原因是:1. 在没有状态机堆栈结构的前提下,是难以实现尾递归的,那么就有可能导致宿主语言堆栈溢出,是有可能而不是必定; 2. 禁用递归采用变通方式不会影响代码功能,反而能让开发者明确知晓此处会产生递归,能有效防止意外情况,权衡之后因而采用。关于后面两个例子,dijkstra 是算法问题,函数更实用,不必强用这种写法来实现,这种写法更适合解决实际中的业务内容。rollback 就更简单了,字段状态重设就好了。

我就这么说吧,你这只是把高级语言的关键字改成符号而已,和什么转换思想没什么关系,简单例子是个封装器,但是一旦到复杂操作就又变回面向过程了...

若你看懂,自不必说........纯纯搞心态的句式.............

无聊,浪费时间

似乎只是 dto 这一层罢了,业务的复杂性是躲不掉的。

要想看着整洁,只能多用几个垃圾袋包起来,然后这几个垃圾袋摆放整齐。但是,垃圾袋内仍然是垃圾。

等到 AI 足够强,都 AI 生成机器码,就无所谓人类可读性了,审美和整洁和艺术等等也都不再重要了

代码没看,看到其他人提到 setTimeout ,即使用 promise 也比 setTimeout 好吧?但是不管哪个,比直接调用都是同步逻辑变异步了。

“不必强用这种写法来实现”,“更适合解决实际中的业务内容”,这已经说明了这种思路的局限性。你要知道,程序员写代码不是为了自己的精神愉悦(更何况这个设计也没办法让大家精神愉悦,当然或许有人觉得这么设计很“高级”吧),要兼顾开发速度、代码质量、维护难度。按照这个仓库里的这种写法,新招进来的员工都骂,出个问题排查半天,性能远不如普通的设计,我没有清楚你推崇这种设计思路的点在哪儿,本身“实际中的业务内容”就不是一个需要解决的痛点,有数不清的方式做。

一个没啥用的华而不实的框架就算了,不少程序员都有这个阶段,本身也算是提升自己编程技术的一个路径,但是一个没啥用的华而不实的框架先吹成“挣脱了思维桎梏,启迪了方向”,再来个订阅制收费,也别说什么人心中的成见是一座大山,单纯是确实配不上。

最后我也不知道你到底是想要卖课还是真的觉得这个框架好,如果是前者那我觉得你来错地方了,显然大家看了之后都觉得问题很多,如果是后者,我建议你可以先问是不是,再问为什么。就这个你发的这个仓库而言,问问 AI 也许都能告诉你为什么这个设计思路没有你说的那么高大上。

自比哥白尼发在 v 站有点屈才了,应该发在更权威的地方,挑战一下你认为的当代的托密勒体系。

那么自信,写的东西却前后矛盾,把你的数据转换链换成函数,只管输入输出,还不是一样说得通。
我也可以说程序的本质是 CRUD ,对吧
另外难道转换规则不算逻辑吗?

你说的是不是数据流编程 / 响应式编程?这些维基百科都有词典的

简单看了一下,感觉基本上就是 vue 的 computed 和 watch ,但是挂在类型上面而不是变量上。

我看不懂,但我大受震撼

我是真看不懂你说的东西跟写的代码,太魔了

哥们儿,你哪个学校毕业的?

什么东西 看不懂啊 老哥 出书

如果你这个语言在某种领域有特殊用途那么还是有存在价值的,例如 julia 对于物理学家。但你这只是讲述概念,没有实操例如性能或者理解方式上与传统语言的对比

打了一大段字又被 V2EX 吞了。很烦,只说重点。

你这就是响应式函数式编程,Makefile 都能干类似的活。规则挂在类型上毫无意义,大部分逻辑不可复用,纯粹增加心智负担。

为什么觉得大家都没想过?有没有可能实际的复杂业务代码在响应式系统编程时就是这么做的,甚至比你想得更深?

附反应式宣言,这是 10 年前的文章 www.reactivemanifesto.org/zh-CN

笑了,老哥可能没了解过 fp

算了,老哥写个排序算法如何

楼主已经领悟到了响应式的真谛。
但倘若我拿出纯 TypeScript 响应式代码而且可以在 Vue3 、React + Valtio 、NestJS 、MikroORM 等几乎所有框架中无缝运行,阁下又该如何应对呢?

www.typescriptlang.org/play/?#code/MYGwhgzhAEAiD2BbAlgO3tA3gKGtY8qEALgE4Cuwx8pAFAA7kBGIyw0T8YpAJgIwAuaCVJoA5gEosAX2y5oYgKbEOXXgCZaUnHjyll5UqmgADACSZiAC2QQAdJ279p0dSfmz5SlY94BmLSx5PQMjUwtrWwc1HnUXP3c8WU8CIhUeJDQMAF5oVEUAdzhM9FoAckYIKzKJOVSIeBBFOxB4MXLffiEygBpoDJR0aKc+WvrG5tb2ss71br6BrOGNMcIGppa2jpi-ef6S+GWePwkgA

本质是数据转换也行,问题是,你倒是说说你怎么样个数据模型把多大的世界包含进去啊?
你说不出个所以然,那我也可以说,有些人发帖的本质是 shit

感觉可以去搞邪教了,云里雾里的

这个没有看懂啥意思 这不是就是一个普通的类吗

觉得最后一段在 CPU 我

太秀了哥

或许你需要一个 rxjs ?

俺也一样,看着文字,一脸懵逼。
看到他文档代码才知道他说的啥。
正常我们是调用函数来改变数据。
而他: 数据发生改变 -> 调用函数

以前我也很喜欢 rxjs 这类的思想,定好结构后让数据自然流过我预设的规则,那些不懂的都是菜狗。
看了 staltz 的演讲,用它的 cycle.js 觉得很牛
这么美丽的结构,仿佛就能解决一切(狗头

  1. 实际情况下也没有多少业务会处理这么复杂的数据流,很多时候局部 + 全局就能解决问题
  2. 接受的人懒得关心整体架构层面上思想再来具体理解你的代码,部分通用抽象加业务层面条可能更好看(虽然持保留态度

这玩意貌似就是懂的人爽,一般人接手大概都是想骂娘的吧,不然函数式编程和响应式编程怎么需要传教呢(狗头保命

首先 挺楼主,从工作中凝练出思想,动手实现,再应用到实际中. 这本身就吊打一众喷子了.
另外,我的理解是这个库是可以大幅度减少很多代码的. 或者说是这个库帮我们简化了很多垃圾代码.
比如 定义一个函数,里面判断数值是否变化,或者是否满足条件了,如果满足则去调用另外一个函数. 跳过这些垃圾代码. 直接考虑的是. 1.条件满足的标志是什么? 2.满足后如何处理?
另外 规则执行时得到的是 Promise 对象.这一点就可以处理很多场景了.
个人感觉非常不错,楼主加油.

题外话,我一般判断一个理论可不可靠,一看有没有引用。如果没有引用就看作者是否业内大佬。 如果没有引用也不是大佬,基本上是民科。其理论可以不看。 如果称这是理论的话。

有点走火入魔的感觉。首先这个理论非常的不新,其次也并不是什么银弹,不可能存在“从传统编程需要根据不同业务需求设计不同的实现过程,到全然不用设计,只套用一条普适的方法就行”。业务逻辑你还是要实现,可能就要换一种很别扭的方式。真想证明的话,拿出一个用这个写的实际项目来看看,很好奇你一直在用是用在哪里。
建议多看看市面上的东西,不要闭门造车了。

你们说的是这个吗?
cn.redux.js.org/

trampoline 可以实现尾递归,我拿来写 shell 也能尾递归

这语气跟饭圈很像,“哥哥都那么努力了”
别只口头支持,订阅一下呗

说话阴阳怪气,这是讨论技术的地方,你一个关注娱乐圈的人,来这里丢人现眼干嘛....无语. 这库你理解解决的是什么问题吗? 呵呵了....

从本质上来说,这个结构没错了,抽象的世界的本源确实很简单。输入,f ,输出,咦这不就约等于图灵机了吗?
但这图景不能放大。因为,事情的复杂度如果是 100 ,被抽象成为 3 了,必然是因为抽象忽略了细节。忽略,并不是消灭,物质是守恒的,复杂度或者说信息也是守恒的,它只能被忽略、被分治、被自顶向下,但不能被消灭。
站在一定 level 看事物依然有价值,就像我儿子站在正数、零、负数的高度看自然数一样,瞬间就把正无穷通过分类法简化到了 3 类。但一个 level 说一个 level 的话,不能因为这个 level 得到了 3 的视图,就说自然数本体也就 3 个对吧?

既然不得不下沉,那就下沉到每个抽象内部去。输入有多少种?世界的真实状态有多复杂,就有多少种。用户输入(各种各样的格式)、自然输入(例如时间)、外部依赖输入(例如网络)、异常输入(这耗费了程序员一半心神)。。。我还能继续数,继续下沉。
f 有多少种?不敢数,怕指头不够,反正我这业务逻辑写了好几 M 了。别说 Fn 的个数,就有限个,排列组合一下呢?键盘上就有限个字母还能排列组合出莎士比亚呢。

不反对哲思,我甚至提倡哲思,不管对不对过程都是值得鼓励的。但反对哲思结论跨层应用。讲个笑话:
老爷吃饭不吃屎, 饭进肚里变成屎。 吃饭变屎多费事,不如当初就吃屎。

#52 你说的这个理解不就是响应式编程? React 状态和钩子,Vue 计算属性和监听器、RxJS 、Redux 、Vuex ,还有楼上老哥给的“纯 TypeScript 响应式代码”不都是?用得着 op 在这故弄玄虚?

k8s 是不是也是这样的。。

好吧 k8s 更多的是声明式 ,虽然都有 event drive 但是响应式 主要强调的是数据的流动