没关注过go模板,扫了一遍这里少数几个有价值的回答,就了解大致咋用了。
go 的模板难看难懂又丑?
能分析清主谓宾定状定补的,就能一眼看明白go模板。
c++ :
template<typename Derived>
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE
typename ScalarBinaryOpTraits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const {
.....
}
你diss的开心就好。
type Numeric interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
complex64, complex128
}
func DotProduct(type T Numeric)(s1, s2 []T) T {
......
}
Numeric 未来会进标准库,你也不用自己定义。
哪种更简洁?
foo(int,int)(2,3) 这种调用当成两段调理解,1.用类型参数具类化函数,2.传实参调。
读起来就比foo<int,int>(2,3)膈应?
不喜欢哪门语言就屏蔽,少浪费自己时间,制造无用噪音。
不断有人喷"万一以后要混用显式的类型参数和普通值呢?没救了。"
灵剑举的例子是这样,这种情况要是又命名不好读起来会费劲些。
但是这种 case 根源来自两个:1.就是ABC说的推导的匹配规则;2.go 可以把值类型直接丢给形参为接口的函数。
前者 ABC 已经说的很清楚。哪天 go team 决定扩大匹配规则就能满足更宽松的自动推导,也不会破坏前向兼容。
况且多数情况 fun(type T Cons(T))(t T) +普通接口就足够覆盖类似 case,不会导致可读性问题。
如果你得用 fun(type T)(t Cons(T)) 表达,让你的代码落在推导失败的分支上,必须显示指定type,也ok呀。注意下命名,代码也不会太难读。
但对比下,go的接口是鸭子类型。你一定得这么写,代表你的等价需求是: 接口+泛型+约束+接口方法也是泛型。
我几乎没遇见过这种需求,但这里毕竟是bhu,人人都有这种需求绝对理解。
但与其操心 go 的 test(String)(StringTImpl{"XXX"})难读又丑,不如考虑下你自己挺的语言表达这个声明得多冗长恶心,你智力能不能一次写全、一次写对吧。
自己又不用,我们这些长期重度用户还没吐槽操心,你操哪门子心?