java链式语法_链式语法的思考

传统的s表达式第一个位置是函数位,后面都是参数。

嵌套的表达式,和嵌套的数据结构(其实也是嵌套的表达式),看起来也挺好的。但C系语法的表达式默认就是链式调用,感觉更符合思维习惯。

通常计算出第一个数据,将数据向后转移。

以js为例,如果是object,可以用点语法访问其键值,如果返回是函数,可以用括号传递参数。

虽然现在很多C系语言滥用链式语法,对通常返回void的函数返回this,好进一步使用链式调用,即参数过多时的builder模式,其实感觉不是很好。

链式反应是自然而然的转移,而不是刻意的,本来返回void返回this,无法从函数签名上推导。

参数过多,应该模仿js,传递匿名object,对应静态语言应该是匿名类(似乎只有java有)。其实面向对象到现在只是在使用它的字段约束,讨论单继承、协议多实现反而使问题复杂化了,像java有了闭包,一切问题都简单了。按照若非必要勿增实体原则,只应该有作为字段约束的协议(类?有默认实现)和其匿名实现(单继承,并只继承一次,即实现)。但目前面向对象没有字段重载,即使kotlin有了空安全仍然没有字段重载,其实只是做一个语法糖也好,更贴近js,更简单明了,我觉得比kotlin的扩展方法DSL更有用(匿名类重载函数与字段),定义更简单,而且有效避免key重复。

S-Lisp当初由于自己考虑不周(加能力有限),将id统统变成id-paths,内部用点分开,只能用于kvs的情况,不像C系语言,中间可以有函数调用,调用完函数继续用点访问返回的kvs。在s表达式中,默认不是链式的,四处寻找答案未果。如今明白,这个问题,需要用DSL来解决。

其实OC当初使用中括号调用,后来也改了C系的链式语法。中括号常常造成左边括号挤一堆,还是在OC是一种面向对象语言的情况下,不必全局定义函数。(中括号叫M表达式,s表达式是因为使用小括号,而我叫S-Lisp却将几种括号都用了,当初并没有深入了解s的含义,尴尬)。链式语法其实就是减少括号的过度嵌套,函数位的嵌套,但并没减少括号,所以会说C的括号并不比lisp少。

思考js中的链式,第一个被求值,可能是id类型,可能是匿名定义的Object或其它带返回值的表达式。后面如果是点,其实隐含了两种情况,一是访问Object本身,二是从原型链上访问方法,访问Object本身可以立即得到,如果后面是函数调用就直接调用了,但从原型链上获得的方法,依赖左边的Object作this调用后面的参数,这里我想了很久,最后结论是如果自己要做,必须作区分,比如目前觉得原型链上访问方法调用应该用->(其实C/C++里也有区分),而且js吃了this的亏,像python将self作为第一个参数,内部避免了this在匿名函数的传递(其实python也没有好的lambda)。如果要支持原型语言,那么类的静态方法是如reduce(vs,fun,init...),但实例调用时就是->reduce(fun,init...),在链式反应中将前面的结果扩展成第一个参数,这在S-Lisp里很简单,extend就行了。

于是定义的chain就是这样的在while的一次循环中,第一个是列表或空,将之前结果作函数计算

在while的一次循环中,第一个是字符.,第二个必须是id,将前面的结果当kvs取这个id的值。

在while的一次循环中,第一个是字符->,第二个必须是id,第三个必须是列表,将前面的结果当kvs计算取出这个id的值(必须得到是函数),将列表extend这个kvs传入这个函数调用。

(chain a [. ffea . eawf -> feaw [ff aef] . fewaf])

因为我要避免副作用,仔细一想其实原型方法并不好用,而且也不是作扩展方法(类似kotlin),如果是静态语言因为类型参与唯一性校验可以函数重载,倒是可以从作用域上寻找函数当作扩展函数来使用。

这种chain定义使用字符串作中介词区分,链式语法都是这样吧,而且C系语法的这个中介词使用可以不用任何空格。如果不使用->,即不必用字符串区分,其实只有两种情况,更简单了。仔细一想之前的kvs-path/kvs-path-run不就是类似的DSL?只是当时只考虑处理kvs,没考虑函数。这种中间的DSL其实很有存在价值,将之前的chain升级命名成chain-plus,重新定义chain,只处理id和列表两种情况,作为kvs-path的升级版。其实复杂度的提升,难免带着性能的下降。

(chain a [fawef [] fe eawf [faew faew] fewaf])

思考chain-plus,会遇到扩展。紧接着就想到to介词,将前面的结果扔给后而一个,后面一个的计算结果应该是函数。以及to-with,其实可以先extend再to。这似乎比Apply更有用。甚至,将数学的+-*/以及布尔运算加进去,仿佛s表达式里有了中缀表达式,只是没有优先级,看起来似乎也贴近自然语言,虽然自然语言是有优先级的(比如我吃了谁的苹果)。

如何扩展?要么依赖作用域上特殊的kvs,要么传给函数一个kvs...其实可以用扩展方法,直接使用作用域上的函数。这时候使用字符串的时间少,都是介词式的函数,接受前后两个参数。其实原生的+-*/布尔也满足需求。没想到这么简单。

建一个名叫infix的函数。

(infix 1+ 2 - 3 extend [2 4] reduce {} ...)

甚至第二个参数不必是列表。

如果表达式默认是infix,会不会简单很多?

kotlin里有infix函数,当初还怪它使问题复杂化,得重新认识。

red语言用定长参数的方式减少括号,我觉得这种减少方式是不是更直观得多,符合思维习惯?

越想越激动,毕竟自然语言用的介词并不多。

仔细分辨其实有几种规则的链式,只接受两个参数的函数(减少括号);前一个extend后一个作参数列表(不会减少括号,有点扩展函数的感觉);后一个extend前一个作参数列表(其实不直观)。apply可以定义为后面可以一直是参数列表,可以反回列表一直供后接的函数调用……而只有在s表达式用第一个前缀区分,这样看来s表达式语法是最简的。

s表达式之所以用括号就是非定长参数,加之动态类型,这与red是不同的。尽量使用非定长参数的函数,如+-*/,可以用在链式语法中(extension)。两个参数的,可以用在infix的链式语法。这两个链式语法都不需要kvs之类的。每种语言有自己的物质形态,怎样使用更为方便(简化语法树),如js使用object与array,进一步培植人的思维习惯。s表达式的同像性,以及函数的可传递性,并不必用宏简化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值