返回值类型有哪些_关于类型的思考

ts用得很爽,实现了我心目中关于类型的想法。类型!=面向对象。类型甚至不是真实存在的,运行期会移除,只是辅助代码编写。类型是别名,本质上只要满足鸭辨就是同一类型。联合类型的区分太智能了,再以联合字符串为本质。字符串的等比较太常用了,在各lisp都成了match语法,进一步走向prolog,像sql分析数据库。

类型有什么用?脚本语言本来有各种基础类型,再标注上各种类型,脱裤子放屁?而且很多复杂的类型手写很困难,在ts里遇到了,java等传统面向对象语言不会遇到,但等效的在不断创建新类型,代码与概念暴增。标注类型能帮我们静态分析,在编译期——类型语言是区分编译期的。可是单独编译效率仍然太低下了,IDE能实时分析实时提示,与其说面向编译,不如说面向IDE,有IDE这么智能的工具应用起来,谁愿意回到刀耕火种的时代。

所以标注准确说不应该叫类型标注,而是面向IDE标注,使用这样的标注方式,IDE能帮你检查。代码是实现需求,标注是获得检查,脚本上的脚本,替代的是单元测试。以字符串联合为基础的ts,其实本身就更完善地覆盖了很多单元测试的情况,少写了很多代码。为什么说是面向IDE而不是说强类型?很多时候手写类型太多,类型间有因果关系,就希望用宏来生成类型,这时IDE实时执行了宏脚本生成了目标类型,也不用一次重构处处修改,代码更内聚了。脱离了IDE谈类型是无稽之谈,编程语言更确切是某种IDE的特定交互方式,IDE就是最智能的人机交互。

验错,提示,重构,是类型的用处。IDE可以对代码序列化反序列化,用json-AST传输转换成另一种语言。IDE应该是方便复制拷贝的文本,容错,下拉提示,错误提示,灵活的输入——有了这些能力,可以用脚本灵活定制IDE。

————————————

量变引发质变,虽然我自制的S-Lisp不带类型标注,但其实很多函数有明确的类型,但如果能明确地写出来,至少可以减少长篇大论的说明吧。但一直也没找到好的方法。

类型是确实存在的,作为S-Lisp的基础类型,列表空布尔字符串数字(int)函数。意味着某些数据,在某些函数的操作下是绝对安全的,但如果是另一种数据,就是低级的错误。比如extend函数的第二个参数只能是列表或空,而不能是布尔/字符串或函数。

因为很多条件分支的嵌套,脚本语言很难检查低级错误,但脚本确实很强大,基本上就是按照人的自然思路来。更别说parse函数等返回的类型的不确定性。脚本语言基本上是一个人是一条龙,三个和尚没水喝。这时候似乎Java是更正式的,Java有强大的重构能力,字段与类型的检查,同时还有匿名类,基本上比其它面向对象语言贴近函数式编程。

我曾简单地设想对基础的内置函数标注类型,在具体计算之外单独做一次基于流程的lambda类型演算,保证系统至少不存在低级类型错误。其实如果从重构角度,有了类型演算的检查,重构也会有保证了。我希望有一种简化版的Java,保留其强大的类型与字段验证、重构能力和匿名类,必要时候可以舍弃类型的概念。

简化的Java,应该舍弃中缀表达式,幸亏Java还没有自定义中缀表达式,不然优先级也是一笔糊涂账。中缀表达式只能接受两个参数,老老实实用括号不会错,如果用的是S表达式就更好了。Java没有重载操作符,这也很好。Java还应该加上空联合,像kotlin一样尽早区分。if语句与while语句应该是函数式的,返回值,尽量无副作用,减少概念...。

总是难免要重构的,尤其是分散的引用,乃至作为库被别人引用。JS系字典作参数,增量的改造可以不处理,破坏性的改造,稳妥的办法就是新建带版本号的函数,旧引用仍然能正常工作,但很丑,同时如果旧函数内部本来存在逻辑问题,就没办法了。功耗可能要大一些。脚本的系统仍然得靠人的统筹管理(不过事实上现在的什么系统不是三五年就过时了?)

既然重大的重构能力与类型演算殊途同归,其实也只是回过头考虑给脚本加上一些限制,使尽量保留脚本的灵活,同时获得类型验证。比如可能parse函数就没有了。如果完全不写类型标识,可能问题比较多的是if语句。

我曾经想联合类型是像TypeScript一样,与空联合也只是普通的一种了。事实上每个列表(元组)类型都不同,函数更不同,便生出析分类型处理的问题,似乎超出了脚本的能力。然而事实上联合的类型多了人也不好分辨,JS等只动态地检查它是空/列表/布尔/函数/字符串,而Java里更只有与空联合,那就只允许与空联合吧。

因为不强制类型转换,可能有个特殊的函数(或标识),比如if-exist-run,将空联合分成两种情况分支去处理。然而和其它if语句一样两种情况只能返回一种类型,或者与空联合,得检查两个分支返回的同一种类型(或内中一种为空)。

如果完全不标注类型,还有一点好处,所有函数都像C++中的泛型函数一样,只要在具体运行场合不出错就OK。在if系语句中如何确定自定义函数的类型?

而且类型隐含了兼容性,比如一个接受任意类型的函数,可以替代任何作参数的特定函数(还有返回值的约束)。kvs属于List,兼容于List的所有操作。

在这其中其实我想到一种类型的表示方法,很S-Lisp,比如

Int/Int?/String/String?/Bool/Bool?
[String Bool ...Int]/[?String Bool ...Int]
{[String Bool]Int}/{?[String Bool] Int}

如果有泛型函数。如果返回值依赖回调函数?

事实上Java是有中间类型的,自定义类型,自定义类型虽然是一种类型的组合,但它是重构的依据,与哪种类型保持一致。一般一个公开的Java类就是一个文件,如果能省下类型标识就更好了。这时函数类型不能传递,if系语句的分支要么返回空,要么返回相同类型构造而成。

Class是返回一组函数,以自己为类型。Function是返回已经定义的Class类型。

类拥有一组函数。函数不能与实例脱离(就退化成传统面向对象)。匿名类与类的构造应该统一,像JS的字典一样。哪些必须重写,哪些可选重写,哪些字典不存在不能重写。函数的参数太长,也应该用字段标识。我们不需要知道类型,但又想获得类型验证的好处。

暂如此...


如果联合类型,如用()表示,可能还有递归引用类型

[...xs] `0~N个相同类型`
[x ...xs] `1~N个相同类型`
([...xs] Int String Bool Function) `即Any类型`
`x是泛型函数的泛型可能依赖于入参的类型`

loop 
{
	[
		{
			[...xs]
			[Bool ...xs]
		}
                ...xs
	]
	[...xs]
}

量变引发质变,而不是质变造成量变,也许是不可逆的。

就像之前这loop函数,if语句的归纳联合类型都不起作用了,真正的返回值根据具体情况来实现。因为loop本身也是靠递归来实现的,是因为它不是最终函数?


突然想到在具体的使用场合,业务逻辑的复杂化,Lambda通常会退化成Object,所以其实Java的Lambda本质是匿名类,是一个正确的思路。必要的时候简写,为了语法的一致不简写也可以,反正能解决问题;简写成Lambda,反正有强类型验证,重构也容易。用类型基本上与DSL无缘了(不考虑kotlin之前,它的DSL中函数没有强制约束实现。其实DSL有XML,它有类型检查,只是稍改下语法就好)。其实我之前写JS大多也成这种面向对象了。

编程中常用到Array与Map,其实就是js中的Array与Object。如果要强类型化,每一种又分为两种,同类型的Array,不同类型的Array(元组);同类型的Map,不同类型的Map(Object)。当业务复杂后,Object很实用,但元组在局部场合也很实用。通常Object带类型名(class),由前面的总结不再传递函数。loop语句也不考虑(Java里有while语句,可能需要进一步封装使函数化,比如两个回调函数,一个主判断,一个主计算),reduce这种Java里也有实现。

将类的实例化与匿名化一体,像js中Object一样键值映射,不区分值与函数,且最好是常不变的。如上,类是返回自身的函数,函数是返回已有类(现在可能是元组)。函数的参数是数组的,如何传Lambda?函数也不能像类一样重写,那么函数传lambda就是接受一个类(重写)。而类实例化是重写,还是接受一个参数(总要重写,重写什么?协议?)类的实例化有构造函数吗?如果是重写,就可能没有。如果是接受参数,就可能有。接受参数实例化,与函数返回,其实是一样的。重写其实是污染原作用域,而且没有构造过程,其实可能需要统一的构造过程。但参数的话(实现契约)就可能需要默认值,不过Java的协议目前也有默认函数(只是不能保存状态),而且个人不是很喜欢多协议实现。类也许不应该继续继承,只能是协议继承,而协议只能单继承,不能保存状态。协议实现为匿名类,作参数传递。如果选择某个协议实现,倒是可能有默认值。协议也没有构造函数。但协议的默认值,似乎接受的类无关,不像js检查某未实现。协议与执行的目标类有关,作为一种外部重写,默认值的处理办法却是妥协的。是否有必须实现与选择实现?则可以检查选择实现是否已经实现,倒是从内部声明默认值。当然协议实现匿名类,必须将未实现的动作都实现,默认实现的当然可以不实现了,最好可能调用super方法?但如果协议允许选择实现,而有语法检查到未实现,也许协议也不继承。但如果有内置默认值,也会面对另一组默认值组合的情况。有一个空的根协议,有一组默认值协议(甚至可以自定义)。然后具体场合选择实现哪一个协议。

集合与字典,需要泛型。如上,只是Java的一个子集。匿名协议实现,构造函数入参。但元组返回呢?可能要常不变。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值