duangsuse::Echo
这类实用性较低的知识,是否希望解释名词
结束洗稿。感觉可能需要一堆正则重构工具,我不想看到「一个一个一个」这样的量词🌶
😅开个玩笑啦,本频道以「编程」原创内容为主,这些只挑重点
呃既然你们觉得这技术也想了解,我之类弄mkey了解了些 讲。没博客也是我的失败,过几个月大概。
关系式 1=1 成立 1=2 不成立
a=1 和 1=a 成立
成立得解,于是程序=目标Goal=等式的所有解
注意,等号是没有方向的。在 #js 有 [x,y]=p 和 p=[x,y] ;看起来是关系式,其实等号左是模式pat、右值expr,关系式里,变量是值、含变量数组[a,1]=[1,a] 也是值-js里 [x,y]就是死模式
(append-out "a" x "abc") Yes. x="bc"
因为『未知量』也是值。
def (appendo a b c)
b=''&c=a |{x r. [x,r]=b&this([a,x],r,c) }
其中this是递归 ab皆链表
如a=c='?' 则成立
如a='1' b='2' 则 f(12,'',c)=a ,知道abc里任何两项都能推完-除非 f('a','','?a')={c!=a} No.
为啥变量也是值?因为语义不是「重写化简:(1+2)=3」而是归一 #fp unification ,即我开头说的 a=1&1=a ,成立, a=1|a=2 ,在不同上下文-各自成立。KV上下文{x r. goal}就是结果,它没有求值 只有a=b=c 相等性传播。这显然涉及数组解构(unify-[a]=[1])、再构(reify/grab v from ctx),别忘了c=12的例子 有1个x变量,c=123 就有两个x 在回溯时=b[0]
实现细节都讲了,式Goal如=, &| {a b.}是组合其它式,得惰性K=Symbol/唯一str -V流的,一般 &会用eachNext([1],[2])=12 做,|就是并联,然后unify "abc"=[x,r]/grab "${x}bc" 都是deep的。un和deepEq类似但能给变量赋值,un失败得null。有变量 a:b,b:c 则 get(a)=c; get(2)=2
可以去 https://github.com/tca/veneer 试试关系式编程。因为相等关系能构成 [],{},"" 数据- 它们都是“算式得出”的,关系式可以实现列表处理和判定-但不能 while(1)print 这种“动作语义”
纯函数式(不含Scheme,rkt 等)也没有,但二者不同。
它可以用于类型推导 #kotlin #ce #typing
fun<T> T.let(op:(T)->R): R 里,类型参数没有上下界,只有「确定性」-每处T不能同时是Int,Date
因此在检查时,第一遍 receiver T 提供T:Int,ParamType 实例 (T)->R 试把自己的 T 与之归一,比如 Int|Number=Number ;第二遍检查 Int. 仍符合 Number.let 的签名,可以调用。
如果是 fun<T> Any.asType():T ,第一遍T没有信息(参数的-类型表达式 里没有使用) 也非T:Any ,推导就失败了;或者推导出 T=Int|Date=Any ,查不到重载,第二遍检查报错
T在编译期是和语法树1:1的data(var actual:Type?),所以 fun rec(x:T)=rec(x-1).plus(1) 也推不出来/不该想那么多
而 val n=1 写明就是 <T>val n:T=1 ,T=typeof 1 ,如写 (n+2)且(+):TT->T 则也有 {T R. n=1 :T & (n+ 2:T):R } 关系式
qunie就是鸡兔同笼这类问题,TDD 是面向🐒跳键盘编程(确信..其实是先写检查),可以穷举也可上关系式,总之mk是挺直白的,确实是pdf界一股清流
https://tttttt.me/ice_learn_arend/199 那么我们来看实际应用
\func wow {U : \Type} {T : U -> \Type} (A B : U) (a : T A) (b : T B) : Nat => zero
wow(U:T F:U->T) AB:U a(FA) b(FB) :Nat=zero
t1(AB:T) x:A y:B =wow ABxy --fail
t2(AB:T) x:A y:B =wow {_} {\. _} A B x x
是啊,是为什么呢🧐 又是怎么用呢
一说SQL和mk同类,只不过是查询既有关系(而且必需SELECT a,b或*),此外有 swi-prolog.org
这也是我发投票 https://tttttt.me/dsuse/17241 的原因
比如 #zhihu 某专栏的作者
浅尝 miniKanren,传说中的逻辑式编程(二) - 吴烜xuan三声的文章 - 知乎
https://zhuanlan.zhihu.com/p/372280127
如果不是因为科普的萎靡,他本来可以做更有价值的事,这难道不值得所谓的PLT人三思吗? #statement
我到底是一个一个一个什么啊(全恼)🥱
😅开个玩笑啦,本频道以「编程」原创内容为主,这些只挑重点
呃既然你们觉得这技术也想了解,我之类弄mkey了解了些 讲。没博客也是我的失败,过几个月大概。
关系式 1=1 成立 1=2 不成立
a=1 和 1=a 成立
成立得解,于是程序=目标Goal=等式的所有解
注意,等号是没有方向的。在 #js 有 [x,y]=p 和 p=[x,y] ;看起来是关系式,其实等号左是模式pat、右值expr,关系式里,变量是值、含变量数组[a,1]=[1,a] 也是值-js里 [x,y]就是死模式
(append-out "a" x "abc") Yes. x="bc"
因为『未知量』也是值。
def (appendo a b c)
b=''&c=a |{x r. [x,r]=b&this([a,x],r,c) }
其中this是递归 ab皆链表
如a=c='?' 则成立
如a='1' b='2' 则 f(12,'',c)=a ,知道abc里任何两项都能推完-除非 f('a','','?a')={c!=a} No.
为啥变量也是值?因为语义不是「重写化简:(1+2)=3」而是归一 #fp unification ,即我开头说的 a=1&1=a ,成立, a=1|a=2 ,在不同上下文-各自成立。KV上下文{x r. goal}就是结果,它没有求值 只有a=b=c 相等性传播。这显然涉及数组解构(unify-[a]=[1])、再构(reify/grab v from ctx),别忘了c=12的例子 有1个x变量,c=123 就有两个x 在回溯时=b[0]
实现细节都讲了,式Goal如=, &| {a b.}是组合其它式,得惰性K=Symbol/唯一str -V流的,一般 &会用eachNext([1],[2])=12 做,|就是并联,然后unify "abc"=[x,r]/grab "${x}bc" 都是deep的。un和deepEq类似但能给变量赋值,un失败得null。有变量 a:b,b:c 则 get(a)=c; get(2)=2
可以去 https://github.com/tca/veneer 试试关系式编程。因为相等关系能构成 [],{},"" 数据- 它们都是“算式得出”的,关系式可以实现列表处理和判定-但不能 while(1)print 这种“动作语义”
纯函数式(不含Scheme,rkt 等)也没有,但二者不同。
它可以用于类型推导 #kotlin #ce #typing
fun<T> T.let(op:(T)->R): R 里,类型参数没有上下界,只有「确定性」-每处T不能同时是Int,Date
因此在检查时,第一遍 receiver T 提供T:Int,ParamType 实例 (T)->R 试把自己的 T 与之归一,比如 Int|Number=Number ;第二遍检查 Int. 仍符合 Number.let 的签名,可以调用。
如果是 fun<T> Any.asType():T ,第一遍T没有信息(参数的-类型表达式 里没有使用) 也非T:Any ,推导就失败了;或者推导出 T=Int|Date=Any ,查不到重载,第二遍检查报错
T在编译期是和语法树1:1的data(var actual:Type?),所以 fun rec(x:T)=rec(x-1).plus(1) 也推不出来/不该想那么多
而 val n=1 写明就是 <T>val n:T=1 ,T=typeof 1 ,如写 (n+2)且(+):TT->T 则也有 {T R. n=1 :T & (n+ 2:T):R } 关系式
qunie就是鸡兔同笼这类问题,TDD 是面向🐒跳键盘编程(确信..其实是先写检查),可以穷举也可上关系式,总之mk是挺直白的,确实是pdf界一股清流
https://tttttt.me/ice_learn_arend/199 那么我们来看实际应用
\func wow {U : \Type} {T : U -> \Type} (A B : U) (a : T A) (b : T B) : Nat => zero
wow(U:T F:U->T) AB:U a(FA) b(FB) :Nat=zero
t1(AB:T) x:A y:B =wow ABxy --fail
t2(AB:T) x:A y:B =wow {_} {\. _} A B x x
是啊,是为什么呢🧐 又是怎么用呢
一说SQL和mk同类,只不过是查询既有关系(而且必需SELECT a,b或*),此外有 swi-prolog.org
这也是我发投票 https://tttttt.me/dsuse/17241 的原因
比如 #zhihu 某专栏的作者
浅尝 miniKanren,传说中的逻辑式编程(二) - 吴烜xuan三声的文章 - 知乎
https://zhuanlan.zhihu.com/p/372280127
如果不是因为科普的萎靡,他本来可以做更有价值的事,这难道不值得所谓的PLT人三思吗? #statement
我到底是一个一个一个什么啊(全恼)🥱
GitHub
GitHub - tca/veneer: miniKanren in the browser
miniKanren in the browser. Contribute to tca/veneer development by creating an account on GitHub.
请问下,这种想把get方法隐藏的功能怎么写呢? #kotlin
Rin:
@Deprecated("Hidden", level = Level.Hidden)
get() = ...
那大概是没办法了,或者多写一个_onCardClickListener
{หऽ∮ಭ》优妮:
直接 get() { throw xxxx}
Rin:
@Deprecated("Hidden", level = Level.Hidden)
get() = ...
那大概是没办法了,或者多写一个_onCardClickListener
{หऽ∮ಭ》优妮:
直接 get() { throw xxxx}
duangsuse::Echo
为了吹哨人、发哨人,以及所有为了疫情努力过的人(当然,显然我不包括在其中) 本频道 image 象征性灰今明两天。 #Telegram #China #Python Pillow: from PIL import Image def grayifyFile(name): img = Image.open(name) img.convert("L").save(name.rsplit(".")[0]) grayifyFile("image.png") OpenCV #CV #Cplusplus:…
#Kotlin 今天再写一遍灰度(黑白)化 🤪
import java.io.File
import javax.imageio.*
import java.awt.image.*
object ImGray{
@JvmStatic fun main(vararg a:String){
ImageIO.read(a[0]).mapPix{val(r,g,b)=Byte.cut(3,it); val l=(r * 299/1000 + g * 587/1000 + b * 114/1000); Byte.cat(l,l,l) }.save(a[1])
}//每Pix=Lum亮度公式
fun BufferedImage.mapPix(op:(Int)->Int)=this.apply{
for(y in 0 until height)for(x in 0 until width)
setRGB(x,y, op(getRGB(x,y)) )
}
fun Image.save(fp:String)=ImageIO.write(this,fp.substringAfter("."),File(fp))
object Byte{
fun cut(n:Int, b:Int)=IntArray(n).also{var u=b; for(i in 1..n){it[i]=u and 0xFF; u=u ushr 8} }
fun cat(vararg b:Int)=b.fold(0){u,x -> u shl 8 or x}
//{var u=0; b.forEach{u=u shl 8 or it}; return u }
}
duangsuse::Echo
The Java maintainers chose to generate the implementation class in runtime. This is done by calling java.lang.invoke.LambdaMetafactory.metafactory. Since the arguments for that call (return type, interface, and captured parameters) can change, this requires…
然后呢华为方舟也是做了个
#java #learn 这个 invokedynamic 呢,暴露为 j.l.invoke.CallSite ,咱看看用法
#code
""?是为了规避常量折叠。无论多复杂,带><转型的常量表达式 sun javac 都是能执行的..妈耶,在框架限制内你可牛
会得到自带的FnRun.<init>=super() 和 main():
..我们用 #python #code 重构一下字节码表示
所以Java闭包为啥不能改
因为代码一样
然后new R(){}的
它被 .invoke() 的地方就是动态调用点(callsite) ,bootstrap 方法(^) 用于查找句柄指代的函数实现,只做一次
没错,invokedynamic 的lookup函数的参大多在编译期确定,甚至不能是 Object 😒
当然用反射newInstance就太容易了,Google dx 使用 RuntimeDesugar 转化^
除了查找函数签名的实现,用户代码不会涉及其他关于计算栈的东西,和最常见的
顺便: invoke-interface 是劣化的 virtual 。虚方法是单继承得来,成员有唯一索引;接口方法可被多 class implements ,无法做覆写查找的缓存。但能去虚化内联时一样
super()的话是 invokespecial ,不能通过继承被覆盖也无需查找
总之这个Java8引入的 INDY 主要是关于性能前提的,如果以 #js 程序员的视角会觉得这些都不如
我不想再谈了,也没啥用;还不如做JVM脚本语言—但也不得不考虑Dalvik dex的兼容性?
拿这种东西当知识不如直接说:
为什么必须用dyn: 没有为什么,也不是因为参数类型不确定。反射交给目标SAM函的NameAndType 也能按照impl的参数(=field)动态定义/init this implements SAMFnType ,来创建
当你写
这些内容太细节,工程界自然完全不知道,所以说是什么“metafactory本身的签名不定” “创建调用的参数不确定” —的确不定,但重点是在T子类this.getClass() 定义不确定,这就涉及闭包,而今天的人都tm不知道{x+1}等函数是有词法上下文,由编译器统一保存位置的! 🥲
因为每个开发者眼前都只有自己的一亩三分地,编程是为效果
然而框架的开发者却不懂这个道理,想传教自己的设计有多“可扩展” 😒
我就好奇啊,中国也没几个人真做字节码框架啊,考的有意义吗? 觉得很厉害??🤔🙏
ref: https://jakewharton.com/d8-library-desugaring/ dex 上 stdlib-jre8 的 hashcode, notnull 测试都转换回老版本了,同时兼容Stream等新API
jbc2mpl && mplcg
的示例,其实主要是移植 #jvm 的感觉, virtualcall
(invoke-virtual, invoke-special/static 是普通函数) 方法查找模式都复刻了,也有些if,while 的高级Node,但许多库..哪怕 javacore/libjavacore.mplt 的 rt.jar 和 j.l.String
都没开源,在 #zhihu https://www.zhihu.com/question/343431810 可以看到#java #learn 这个 invokedynamic 呢,暴露为 j.l.invoke.CallSite ,咱看看用法
#code
class FnRun{javap -c FnRun FnRun$R
interface R{void run();}
static R f1;
static public void main(String[]a){
f1="".isEmpty()? ()->{ a[0]=""; } :new R(){public void run(){a[1]="";} };
}
}
""?是为了规避常量折叠。无论多复杂,带><转型的常量表达式 sun javac 都是能执行的..妈耶,在框架限制内你可牛
会得到自带的FnRun.<init>=super() 和 main():
..我们用 #python #code 重构一下字节码表示
//L5 "".isEmpty在非static 方法里 aload_0=this 。在这里
ldc String
Fvirt String.isEmpty:()Z
5^ifeq //br.not
aload_0
Fdyna #,0:run:([String;)LFnRun$R; //重点!
14^goto
new FnRun$1 ^5 //here
dup
aload_0
Fspec FnRun$1."<init>":([String;)V
putstatic f1:LFnRun$R; ^14 //goto
//L6
return
new FnRun$1(a)
被翻译为 new, dup, (a) Fspecial, putstatic
即 {R o=new R; init(o); f1=o}, o值引用了两次所以Java闭包为啥不能改
()->{a=new String[]{};}
,在()->{}外也不行? —因为它就是个构造器,Kotlin 使用 IntRef
化来实现完整的局部量共享。因为代码一样
Fdyna
直接初始化了 FnRun$R.run
,然后 callsite$0 开 javap -v 才能看到,待会说然后new R(){}的
class FnRun$1 implements FnRun$R {Java8的动态调用不止是新增opcode
final java.lang.String[] val$a;
//<init>: L5
aload_0
aload_1 ; putfield val$a:[String;
aload_0
Fspec Object."<init>":()V
return
//run:L5
aload_0 getfield val$a:[String;
iconst_1
ldc String#3
aastore //还有iastore fastore..IntArray啥
return
j.invoke.MHs.lookup().findVirtual(Obj,"hashCode",methodType(int))就是方法句柄
它被 .invoke() 的地方就是动态调用点(callsite) ,bootstrap 方法(^) 用于查找句柄指代的函数实现,只做一次
Fdyna 0:run:([String;)LFnRun$R;callsite$0 REF_invokeStatic=
invoke/LambdaMetafactory.metafactory:(Linvoke/MethodHandles$Lookup;LString;Linvoke/MethodType;
Linvoke/MethodType;Linvoke/MethodHandle;Linvoke/MethodType;)Linvoke/CallSite;
明显这个 metafactory(Lookup,String,MethodType,...)
做了字节码new
的工作,只接受 aload_0(this) 和 FnRun.lambda$main$0:([LString;)V的NameAndType 就创建了内部类 FnRun$R 的对象,这一步只是“调用一个尚不存在的class构造器”,我们负责生成&加载相关类 🤔,并链接-给出代码位置
-Djdk.internal.lambda.dumpProxyClasses=.但剩下的3参数太多了: SAM methodType(void.class), implMethod, 泛型SAM描述符
没错,invokedynamic 的lookup函数的参大多在编译期确定,甚至不能是 Object 😒
当然用反射newInstance就太容易了,Google dx 使用 RuntimeDesugar 转化^
lambda$
,当然这都是过去式了, #Kotlin 万岁super<PT_2>.say()的自由祖父类指定可以用:
class PT_2 {void say();//parent T你不能手写 invokedynamc 而只能由 j.l.invoke.* 工具类invoke()时生成,因为调用是在字节码层,不是运行期元数据反射 😒
class PT extends PT_2 {}
class T extends PT{void say(){}//新版本
void main(){
MHs.lookup().findVirtual(ParentT_2.class,"say",MT.methodType(void.class)).bindTo(this).invokeExact();
}
除了查找函数签名的实现,用户代码不会涉及其他关于计算栈的东西,和最常见的
invokevirtual
是完全一样的,而因为lookup的实现有限制, MHs
提供了 collectArguments,guardWithTest,countedLoop
等一系列组合器帮助修改调用,比如加点参数,对Groovy 不定长参 函数转化 这样就很有帮助顺便: invoke-interface 是劣化的 virtual 。虚方法是单继承得来,成员有唯一索引;接口方法可被多 class implements ,无法做覆写查找的缓存。但能去虚化内联时一样
super()的话是 invokespecial ,不能通过继承被覆盖也无需查找
总之这个Java8引入的 INDY 主要是关于性能前提的,如果以 #js 程序员的视角会觉得这些都不如
new Proxy({}, {get,set})
😂我不想再谈了,也没啥用;还不如做JVM脚本语言—但也不得不考虑Dalvik dex的兼容性?
拿这种东西当知识不如直接说:
SAMFunc/*void()*/ f=()->{}
编译期生成对 j.l.invoke.LambdaMetaFactory
静态同名方法(Lookup,String name,MethodType)
的调用,并把结果CallSite
(仅首次计算)再次调用;这个“元工厂”把()->{}代码生成为 new T(){} 的具体class加载,返回它 static get(...localvars)
的调用句柄,于是得到目标接口的对象为什么必须用dyn: 没有为什么,也不是因为参数类型不确定。反射交给目标SAM函的NameAndType 也能按照impl的参数(=field)动态定义/init this implements SAMFnType ,来创建
o.impl()
的代理。Android 最初就是反射直接Proxy class当你写
class Out{int a; new T(){a} }
,相当于生成一个 Out$1 extends T
,它的构造器把(编译器确定共享序的)局部变量存在this,内部代码是有两个上下文的,()->{} 里也一样,只是这次 Out$1
的创建由运行时metafactory()负责,动态链接 T getLambda(int a);
完全是 Oracle 的私货,Kt 1.5 才支持这个 code size 优化这些内容太细节,工程界自然完全不知道,所以说是什么“metafactory本身的签名不定” “创建调用的参数不确定” —的确不定,但重点是在T子类this.getClass() 定义不确定,这就涉及闭包,而今天的人都tm不知道{x+1}等函数是有词法上下文,由编译器统一保存位置的! 🥲
因为每个开发者眼前都只有自己的一亩三分地,编程是为效果
然而框架的开发者却不懂这个道理,想传教自己的设计有多“可扩展” 😒
我就好奇啊,中国也没几个人真做字节码框架啊,考的有意义吗? 觉得很厉害??🤔🙏
ref: https://jakewharton.com/d8-library-desugaring/ dex 上 stdlib-jre8 的 hashcode, notnull 测试都转换回老版本了,同时兼容Stream等新API
Zhihu
如何看待方舟编译器于 2019 年 8 月 31 日开源? - 知乎
华为表示 show you the code,希望有大佬可以借此机会解释解释何为方舟编译器?
http://www.yinwang.org/blog-cn/2015/04/03/paradigms
“JS 没法访问外层的 this,非得“bind”一下。Python 的变量定义和赋值不分,所以你需要访问全局变量的时候得用 global 关键字,后来又发现如果要访问“中间层”的变量,没有办法了,所以又加了个 nonlocal 关键字。Ruby 先后出现过四种类似 lambda 的东西,每个都有自己的怪癖…… 有些人问我为什么有些语言设计成那个样子,我只能说,很多语言设计者其实根本不知道自己在干什么。
🤔其实这是半对半错的。var self=this 问题可以用 ()=> 解决了,Python3 的 nonlocal 也不是没意义的,比 Java 的
尽管它们都不如 Kotlin 。你看王垠批判Go,质疑 Rust ,但他敢直接怼Kt 的语言设计吗?只好捡了没
http://www.yinwang.org/blog-cn/2013/04/01/lazy-evaluation
Haskell 的参数惰性计算确实需要一个0参闭包,而且是运行时的,较难优化 🤔 所以我觉得如果用指针set 去init 一个变量比较好,然而实际上
Unification(值/变量归一求解) 能用于简单类型系统,且不能推导 subtype 交集,他的逻辑性质名词(symm对称性)也是对的
代数数据类型(带类型参的 Sumtype brach) data A t { Lit :: Int->A Int ; Obj :: t->A t } 其实在 subtype+typeparam 里也能做吧
后来我还在这里看到 recursive type 是指
我以前都把 Bool*Bool=4 state, B+B=2 当冷知识看,没想到真有人把它当东西,置顶一个计科专业还说类型 +* ,还有 0=Void 1=() .. 于是 0*1=0, 0+1=1 ?还不如 insect/union 直白呢. [绝对报错/无尽]计算&T=Nothing, 它|T=T ,因为能算到的Nothing?就肯定不是throw,exit()等,所以意义? 我跟数学老师说 Sigma_i=0^6 表示不如 (0..6).sumBy{} ,老师说那不过是个形式,无关意义。
乱ref英文名词和小众概念,老实说我现在是完全不吃这一套,要么你给我讲明白、指出我的误解,要么拿代码和解决的问题来, 抽象代数x编程,只当耳边风;要是具体一点还夸你厉害,毕竟大家都没空了解这些碎片,我怎么知道你有逻辑自恰性,或者只是碰巧通过检查的数学摘抄?
不过缩进文法(layout) 是香的..也没严重影响解析器的复杂性
http://www.yinwang.org/blog-cn/2014/04/18/golang
这个点评就写得不错,尤其是 TSorter{Swap,Len, Less} 真的比java.Comparator弱智了。
妈的, callback 都能叫 CPS(不返回编程/面向程续编程),这么一想也是噢,调用能决定之后的取舍,怎么不是CPS形式.. Kt协程就是把 suspend fun 加个 callback 交互,因为它没有 TS 的 __awaiter 也不便用闭包this做Generator吧. 再通过StateMachine yield恢复 #kotlin
这里就体现了王垠这人是有真才实学的, 他的知识集不比 #zhihu 一众(公知都算不上,因为从不做科普)的PLT人差
很可惜后来越来越极端,而且也不乐意分享他的compiler.ss外一些其他成果;但就讲课&讲故事而言,
我觉得知乎的大家都没资格评价这个人,因为你们在这点甚至不如他.. 他的博客确实没逼格,话也没轻没重,但对CS科普的贡献是巨大的,真的不夸张。
大家都喜欢轻视「娱乐编程界」,但仔细想想,我们何尝不是娱乐编程人士? 你的回答里贴了多少思路和代码,有多为提问者和公众程序员着想?
如果是为自娱自乐,不算在另一种娱乐编程吗?
ps. 我是不认为太自我的「个人博文」能算科普的。科普必须对不同做法有一定了解,有穿插和客观解读比对,告诉大家好坏要点,而不是代码的解说。不然本质上和"Java入门"教程也没区别
“JS 没法访问外层的 this,非得“bind”一下。Python 的变量定义和赋值不分,所以你需要访问全局变量的时候得用 global 关键字,后来又发现如果要访问“中间层”的变量,没有办法了,所以又加了个 nonlocal 关键字。Ruby 先后出现过四种类似 lambda 的东西,每个都有自己的怪癖…… 有些人问我为什么有些语言设计成那个样子,我只能说,很多语言设计者其实根本不知道自己在干什么。
🤔其实这是半对半错的。var self=this 问题可以用 ()=> 解决了,Python3 的 nonlocal 也不是没意义的,比 Java 的
int a;new T(){a=1;} Error: effective final
好,因为闭包一般不会mut变量,乃至 global ;然后 Ruby 的 ->(){} 和 do|| , Proc.new(&f) 确实是有严重问题,这方面它不如 Python , Matz 对技巧太贪心了。像 C# 尽管技巧多也不会出现函数值有几种写法的问题,但一入 Ruby 你就要学会 1.yield_self{|x| } 和 do|x| end 这些... 坦白说不值,但Rb是有历史包袱.尽管它们都不如 Kotlin 。你看王垠批判Go,质疑 Rust ,但他敢直接怼Kt 的语言设计吗?只好捡了没
throws Exception
强制检查的问题(然而 runCatching{}.getOrNull 用的香谁会管他呢http://www.yinwang.org/blog-cn/2013/04/01/lazy-evaluation
Haskell 的参数惰性计算确实需要一个0参闭包,而且是运行时的,较难优化 🤔 所以我觉得如果用指针set 去init 一个变量比较好,然而实际上
if(!init)x=initizr();
里这个if确实要执行成千上万次,除非动态改汇编。也不是编译能优化的”解释器开销“Unification(值/变量归一求解) 能用于简单类型系统,且不能推导 subtype 交集,他的逻辑性质名词(symm对称性)也是对的
代数数据类型(带类型参的 Sumtype brach) data A t { Lit :: Int->A Int ; Obj :: t->A t } 其实在 subtype+typeparam 里也能做吧
后来我还在这里看到 recursive type 是指
type R= T0+ Int*R
(常规意义: +=| *=,),于是 T0*Int*Int 都是这种.. 就是编译期允许递归 Type.check(inst:Type) 吧.. 算了,唉,我只是讨厌没有编译期计算我以前都把 Bool*Bool=4 state, B+B=2 当冷知识看,没想到真有人把它当东西,置顶一个计科专业还说类型 +* ,还有 0=Void 1=() .. 于是 0*1=0, 0+1=1 ?还不如 insect/union 直白呢. [绝对报错/无尽]计算&T=Nothing, 它|T=T ,因为能算到的Nothing?就肯定不是throw,exit()等,所以意义? 我跟数学老师说 Sigma_i=0^6 表示不如 (0..6).sumBy{} ,老师说那不过是个形式,无关意义。
乱ref英文名词和小众概念,老实说我现在是完全不吃这一套,要么你给我讲明白、指出我的误解,要么拿代码和解决的问题来, 抽象代数x编程,只当耳边风;要是具体一点还夸你厉害,毕竟大家都没空了解这些碎片,我怎么知道你有逻辑自恰性,或者只是碰巧通过检查的数学摘抄?
不过缩进文法(layout) 是香的..也没严重影响解析器的复杂性
http://www.yinwang.org/blog-cn/2014/04/18/golang
这个点评就写得不错,尤其是 TSorter{Swap,Len, Less} 真的比java.Comparator弱智了。
妈的, callback 都能叫 CPS(不返回编程/面向程续编程),这么一想也是噢,调用能决定之后的取舍,怎么不是CPS形式.. Kt协程就是把 suspend fun 加个 callback 交互,因为它没有 TS 的 __awaiter 也不便用闭包this做Generator吧. 再通过StateMachine yield恢复 #kotlin
这里就体现了王垠这人是有真才实学的, 他的知识集不比 #zhihu 一众(公知都算不上,因为从不做科普)的PLT人差
很可惜后来越来越极端,而且也不乐意分享他的compiler.ss外一些其他成果;但就讲课&讲故事而言,
我觉得知乎的大家都没资格评价这个人,因为你们在这点甚至不如他.. 他的博客确实没逼格,话也没轻没重,但对CS科普的贡献是巨大的,真的不夸张。
大家都喜欢轻视「娱乐编程界」,但仔细想想,我们何尝不是娱乐编程人士? 你的回答里贴了多少思路和代码,有多为提问者和公众程序员着想?
如果是为自娱自乐,不算在另一种娱乐编程吗?
ps. 我是不认为太自我的「个人博文」能算科普的。科普必须对不同做法有一定了解,有穿插和客观解读比对,告诉大家好坏要点,而不是代码的解说。不然本质上和"Java入门"教程也没区别
duangsuse::Echo
#plt 呃,这几天眼睛有点疼,那个网页重构也接近尾声了(目的就是交个PR),马上把雄狮扭眼的”热度蹭完“,我就能开始二进制pybind了 ……但是到2月我就必须开始制作一个H5动画礼物,以现在这个效率…… (而且之前说的 Java 入门又鸽子了,尽管对话框和离线javac的问题解决,其他内容还是需费精力 说真的我没一次蹭上国内热度,因为每次都是我趁机学了些”没用的“(比如彩字符画、粒子动画、MBR程序、C指针和数组啦),然后数据不好看 😂 这次也是一样,我用shift重映射圆心距l=1~len 环上像…
对正常人的理解,做编程语言是要能运行的,也有配套代码高亮规则/REPL/网站示例 之类的最低工具集,当然REPL的功能(Tab,历史,高亮)都类似,ANSI终端上 bash 用的 GNU readline 和 node repl{eval,log-writer,completer} 都可以拿来测试
如果说语言是要执行或变成数据(Makefile),
leX-Yacc 的X-Y根本无关这个目的(这个Y根本不是解,因为BNF,PEG本身就是很弱的DSL”领域专有“语言),学下来最后发现自己什么都不会做,一个简单的”数据定义语言“也得费很大功夫
不懂行的人都觉得 school 厉害,其实它各种层面上只教过时的东西,好好想想,如果人家能跟业界平分秋色,为啥不来分一杯羹呢?这又不是传统科学
真正懂编程语言的人不会随意设计(或拓展预处理)语言或类似的东西(隐式注入值,大宏,.),除非这个问题已经到常规写法不能解决的程度(例如 Java 的 null问题和 Builder.this 链),像内联XML和JSON 文法这样的东西,是给常量加糖(混淆语言的数据定义和功能步骤),偶尔用用还乐呵,当个宝就会有人让你知道啥叫行为艺术(配置文件全内联js里,因为默认值垃圾!),所以 #Kotlin 里只有
就像你老重复写一个动词,为许多同类HTTP接口操作专门弄堆fun,不代表你理解框架,只能显得很傻,所以 Kotlin 可以给 fun/A.(T)->R 指定 this (扩展函数)
为什么懂语言结构的处理,反而要(在实验外)规避真正做它? 因为我们明白,若非语言真的优化了一个系统性问题,它只是制造麻烦。知道 for(decl;cond;tail) 很厉害,自由变形AST都能做许多,但也只是玩具——如果我能在编写时避免含糊,就没有后续问题。
如果新语言命名语序和别人相同,那要它干嘛? 否则,就让用户重复学习(例如”汉化“关键词和stdlib),而又不写转译器(Kotlin做得很好),是很头疼的。(没错,我能感到用户的头疼😅)
因为我们知道语言也有开销和收益,它不是最终问题,所以不随便创建它。如果你真的把「语言」当成问题,或顺带框架概念去讨论些简单的算法,就会把简单搞复杂、难调试。
>摘要:
举个例子,S表达式就能表示HTML🙃。有人想过拿JSON保存这个吧,但是因为含大量children:[]被怼,但S表达式
现在不少人就把它的影子当新DSL呢!我们是不是该说这是「历史倒流」呢🌝
毕竟大家开始学编程时都是按直觉的,
你把东西写长,不会让它更”生产“或”可配置“ ”易懂“;写短,不会”更快“或”有内涵“,语义不多不少,它就在那。我觉得这是仍没见过汇编的程序员该有的认识。不知道为什么,重视语义的人很少,仿佛世界上只有语法和”JSON,YAML“这些名字,而操作它们的库API也都是孤立的,并不存在一个”概念“把所有的一切语法和表象连起来。
如果说语言是要执行或变成数据(Makefile),
leX-Yacc 的X-Y根本无关这个目的(这个Y根本不是解,因为BNF,PEG本身就是很弱的DSL”领域专有“语言),学下来最后发现自己什么都不会做,一个简单的”数据定义语言“也得费很大功夫
不懂行的人都觉得 school 厉害,其实它各种层面上只教过时的东西,好好想想,如果人家能跟业界平分秋色,为啥不来分一杯羹呢?这又不是传统科学
真正懂编程语言的人不会随意设计(或拓展预处理)语言或类似的东西(隐式注入值,大宏,.),除非这个问题已经到常规写法不能解决的程度(例如 Java 的 null问题和 Builder.this 链),像内联XML和JSON 文法这样的东西,是给常量加糖(混淆语言的数据定义和功能步骤),偶尔用用还乐呵,当个宝就会有人让你知道啥叫行为艺术(配置文件全内联js里,因为默认值垃圾!),所以 #Kotlin 里只有
listOf,mapOf
而无 []{} 数据,老爱复制粘贴的人到这也就顿悟了——原来 Map 是由 Pair<K,V> 组成的..就像你老重复写一个动词,为许多同类HTTP接口操作专门弄堆fun,不代表你理解框架,只能显得很傻,所以 Kotlin 可以给 fun/A.(T)->R 指定 this (扩展函数)
为什么懂语言结构的处理,反而要(在实验外)规避真正做它? 因为我们明白,若非语言真的优化了一个系统性问题,它只是制造麻烦。知道 for(decl;cond;tail) 很厉害,自由变形AST都能做许多,但也只是玩具——如果我能在编写时避免含糊,就没有后续问题。
如果新语言命名语序和别人相同,那要它干嘛? 否则,就让用户重复学习(例如”汉化“关键词和stdlib),而又不写转译器(Kotlin做得很好),是很头疼的。(没错,我能感到用户的头疼😅)
因为我们知道语言也有开销和收益,它不是最终问题,所以不随便创建它。如果你真的把「语言」当成问题,或顺带框架概念去讨论些简单的算法,就会把简单搞复杂、难调试。
>摘要:
举个例子,S表达式就能表示HTML🙃。有人想过拿JSON保存这个吧,但是因为含大量children:[]被怼,但S表达式
(div.wtf (id xx) (a (href xx title 上级))
就能表示HTML-DOM。现在不少人就把它的影子当新DSL呢!我们是不是该说这是「历史倒流」呢🌝
毕竟大家开始学编程时都是按直觉的,
int n; new ListSeter(){ void f(List a){a[0]=n;} }
里new了的Type实质是函数(SAM单方法接口),而SAM实质又是包含n和算式的数据(闭包),for(i0;i<;i++)
是 for(i in 0..N)
这样都没想过吧。 框架定义,我就用,这是外国 Java 在 Kotlin 出现后如此被动的原因。 😅你把东西写长,不会让它更”生产“或”可配置“ ”易懂“;写短,不会”更快“或”有内涵“,语义不多不少,它就在那。我觉得这是仍没见过汇编的程序员该有的认识。不知道为什么,重视语义的人很少,仿佛世界上只有语法和”JSON,YAML“这些名字,而操作它们的库API也都是孤立的,并不存在一个”概念“把所有的一切语法和表象连起来。
duangsuse::Echo
https://zhuanlan.zhihu.com/p/34064655 #zhihu #fp 这是个物理爱好者18年的 CPS 解释器实现文 这个代码质量.. 其实我是讨厌看lisp 系的,非常讨厌嵌套括号,而且这个人似乎在代码里插debug print ,以C的方法写Racket .. ,那我就把要点挑出来看看 函数式除了伪递归也可做尾调用优化,当 f=()=>g(), g=()=>1 时g可return 到f.retAddr ,类似函数内联。CPS也是尾调用 显然return/即 callstk.pop()…
#PLT #Kotlin 作为编程语言爱好者的我怎么能「只知其一不知其二」呢? 😤x
我对VM/struct,GC(空闲链表标记清除) 都有了解,可就是不懂栈->寄存器 和 Kotlin CPS 不靠 #JS Generator awaiter 怎么实现 async 调用等待
1. 并不是最大栈高度=寄存器数,1+2*3 按结果看有2个,但其实1就够了
思考 x+2*3 ,其实只要1寄存器,但 x+2*a.n ,因为数字和obj 冲突需要两个,那么 a.n.inc 这样的计算链其实也只要一个寄存器!是关于类型的吗? 尽管Dalvik 寄存器有类型
思考 (1*2)+(3*4) ——是因为运算优先级吗?其实是临时位置! 如果 1*2*3 , (2)*3 的位置就可复用,但 *+* 里先算的俩就需2寄存器,+ 在其一上计算
x+(2*a.n) ,首先 a.n 然后 2* 在其上计算,最后+x ... 其实就是一个SSA问题。 但把+-*/. 变节点并不难,就是分配不知咋写..
后计算的尽量复用先算结果的位置,栈->寄存器指令
break/continue 们串成链表,while 结束回填
if jmp-B a jmp-C else b c 记录俩位置,else 回填 jB, end 回填 jC 。递归下降法兼容 if else if 嵌套
2. Kotlin协程和ES6都是基于变量闭包+状态机化,但 JVM 没有 awaiter(IO loop,负责帮忙等待yield的任务并resume 其func*,因此嵌套等待 yield 就行了)
在状态对象上ES6是 Generator{then,throw},Kotlin 是 Continuation{context,resume/WithException} ,分别在this、末参数
在Lua里是基于 lua_State(虚拟机)单步执行权,就有点像pthread了。 但不管Kt,Py,ES6,Lua 的 await/async 都是基于协程实现。 我觉得 CPS 化的最优雅 😊 新学到
StateMachine 是自动生成基于context的cont.resume实现。 在 suspend? fun 内调用休眠函数自会生成其 Cont 实现,把自己的cont注册给它就行
类似ES6(yield),函暂停的位置肯定有 suspend fun 调用,CPS变换给它加自身cont 参数(这是自动回调吗.. 好吧也算),挂起回调度器Dispatcher ,与 __awaiter 不同的是f把 f1.then(cont=f) 指派好了(ES6就不行,因为你要返回调度队列让它找机会的,不能私自叫then 。但Kt 就支持调用时手动指定何时真Cont)
状态机化就是 swith case 0:f(); st++ return; case 1: 这样的
实现上如果内部 suspend call 此次未挂起,自身也直接继续而不会返回调度
这么说:
本来只期望await的暂停,结果全暂停了,因为 runBlocking 会等待所有内部suspend fun
其实就有3断续函数,作用域(基于Scope继承)在它内的 async{} 就等待,外的就得显式 await
https://zhuanlan.zhihu.com/p/156030219
我对VM/struct,GC(空闲链表标记清除) 都有了解,可就是不懂栈->寄存器 和 Kotlin CPS 不靠 #JS Generator awaiter 怎么实现 async 调用等待
1. 并不是最大栈高度=寄存器数,1+2*3 按结果看有2个,但其实1就够了
思考 x+2*3 ,其实只要1寄存器,但 x+2*a.n ,因为数字和obj 冲突需要两个,那么 a.n.inc 这样的计算链其实也只要一个寄存器!是关于类型的吗? 尽管Dalvik 寄存器有类型
思考 (1*2)+(3*4) ——是因为运算优先级吗?其实是临时位置! 如果 1*2*3 , (2)*3 的位置就可复用,但 *+* 里先算的俩就需2寄存器,+ 在其一上计算
x+(2*a.n) ,首先 a.n 然后 2* 在其上计算,最后+x ... 其实就是一个SSA问题。 但把+-*/. 变节点并不难,就是分配不知咋写..
后计算的尽量复用先算结果的位置,栈->寄存器指令
break/continue 们串成链表,while 结束回填
if jmp-B a jmp-C else b c 记录俩位置,else 回填 jB, end 回填 jC 。递归下降法兼容 if else if 嵌套
2. Kotlin协程和ES6都是基于变量闭包+状态机化,但 JVM 没有 awaiter(IO loop,负责帮忙等待yield的任务并resume 其func*,因此嵌套等待 yield 就行了)
在状态对象上ES6是 Generator{then,throw},Kotlin 是 Continuation{context,resume/WithException} ,分别在this、末参数
在Lua里是基于 lua_State(虚拟机)单步执行权,就有点像pthread了。 但不管Kt,Py,ES6,Lua 的 await/async 都是基于协程实现。 我觉得 CPS 化的最优雅 😊 新学到
StateMachine 是自动生成基于context的cont.resume实现。 在 suspend? fun 内调用休眠函数自会生成其 Cont 实现,把自己的cont注册给它就行
类似ES6(yield),函暂停的位置肯定有 suspend fun 调用,CPS变换给它加自身cont 参数(这是自动回调吗.. 好吧也算),挂起回调度器Dispatcher ,与 __awaiter 不同的是f把 f1.then(cont=f) 指派好了(ES6就不行,因为你要返回调度队列让它找机会的,不能私自叫then 。但Kt 就支持调用时手动指定何时真Cont)
状态机化就是 swith case 0:f(); st++ return; case 1: 这样的
实现上如果内部 suspend call 此次未挂起,自身也直接继续而不会返回调度
这么说:
runBlocking{
GlobalScope.async{delay}.await
async{delay}//reset timer
}
本来只期望await的暂停,结果全暂停了,因为 runBlocking 会等待所有内部suspend fun
其实就有3断续函数,作用域(基于Scope继承)在它内的 async{} 就等待,外的就得显式 await
https://zhuanlan.zhihu.com/p/156030219
知乎专栏
Kotlin Coroutine 的 CPS 变换
一般 coroutine 的实现大多基于某种运行时的 yield 原语,然而 kotlin 并没有这种下层支持,在没有 yield 指令支持的 jvm 上仍基于 CPS 变换实现出了 coroutine 其实很厉害,想了解一下是怎样做到的。CPS Transfor…
dnaugsuz
sortBy{it.isMale} 就能做 partition 了( 确实 Kotlin 这有点hack,可能是为了内部优化 #Kotlin 有些小瑕疵,比如 listOf(break,return,throw Error()) is List<Nothing> 还有 run apply 是 let also 同类但命名完全不同,本来是 fun()=run{} 的,可官方自己也不用此写法
问题:
其实 Kt 的问题不少,比如 Common 改名 Multiplatform 还有些隐藏关键字(typeof..),型参约束可以用 where,主要是太实验性,1.3 的时候字节码生成还有问题,不支持 j.l.invoke API
甚至一些?类型优化也有bug
但Kt确实是 #java JVM编程现阶段最好的选择,full interop ,完善带extfun OOP (只是Android上默认proguard规则还不够好什么的……
当你第一眼看某大佬的Kt 时着实被 let run constructor init companion 这些搞眼花了…… 一时觉得比Rust不明觉厉 🤪 Kotlin 初期的stdAPI命名 是个问题
>啥叫partition
school.partition(男女)
>不是有groupBy了吗
school.groupBy(领导教师学生)
那么 associate (toMap,还带 By-With介词) 和 all,any,none ("exists"=any,none=allnot) 也很容易忘,尽管相比JS和Scala 这是最好的
谈到Kt冷知识,我想再提 UnsafeVariance https://tttttt.me/dsuse/15959
我能断言指定
其实它本身同时是 in, 但为了写存储的兼容被迫暂作 out 了而已。
然后匿名 object{} (即
#recommend #kotlin #scala #reveng 关于coro底层的代码示例 https://tttttt.me/kotlin_cn/25062
呃,今天才知道 Kotlin 的 Boolean 是 Comparable, true > false 。感觉有点坑啊
其实 Kt 的问题不少,比如 Common 改名 Multiplatform 还有些隐藏关键字(typeof..),型参约束可以用 where,主要是太实验性,1.3 的时候字节码生成还有问题,不支持 j.l.invoke API
甚至一些?类型优化也有bug
但Kt确实是 #java JVM编程现阶段最好的选择,full interop ,完善带extfun OOP (只是Android上默认proguard规则还不够好什么的……
当你第一眼看某大佬的Kt 时着实被 let run constructor init companion 这些搞眼花了…… 一时觉得比Rust不明觉厉 🤪 Kotlin 初期的stdAPI命名 是个问题
>啥叫partition
school.partition(男女)
>不是有groupBy了吗
school.groupBy(领导教师学生)
那么 associate (toMap,还带 By-With介词) 和 all,any,none ("exists"=any,none=allnot) 也很容易忘,尽管相比JS和Scala 这是最好的
谈到Kt冷知识,我想再提 UnsafeVariance https://tttttt.me/dsuse/15959
(items[i] as IO<IN, in @UnsafeVariance T>).show(s, v)这关于
IO<INPUT, T>
的定义,T 是 out 的,不然 Seq<Any>(io1:<String>,io2)
就会报错,如果要把 Reader 和 Writer 写在一起就会出问题,但代码复用偏偏必须写一起我能断言指定
items: List<(IN)->R>
位置[i]
的 show 可以接受(in) T ,因为它本来就是被取并集损失了精度的,于是写了这种代码,其实它本身同时是 in, 但为了写存储的兼容被迫暂作 out 了而已。
然后匿名 object{} (即
new ArrayList(){{add(1)}}
,常量糖..)的IDE特性也很多,不过 inner class 才正常呢……#recommend #kotlin #scala #reveng 关于coro底层的代码示例 https://tttttt.me/kotlin_cn/25062
Telegram
duangsuse::Echo
上逆变 是什么😳
(T as T1) 的转换?如果是类型安全的话就子类型兼容了,为什么要靠强转断言类型安全?
嗯…… 如果你说有类型损失的,需要断言回来(UnsafeVariance),我这有个例子 ,但是代码复用整到这个程度,估计也没谁了🌚(草
items 的是 <out T>, 如果安全的话就把 out 去掉,但那就不能真正做到 Tuple 的复用了。
我能断言指定 items[i] 位置的 func 可以接受 T ,因为它本来就是被取并集损失了精度的,于是写了 (items[i] as Con…
(T as T1) 的转换?如果是类型安全的话就子类型兼容了,为什么要靠强转断言类型安全?
嗯…… 如果你说有类型损失的,需要断言回来(UnsafeVariance),我这有个例子 ,但是代码复用整到这个程度,估计也没谁了🌚(草
items 的是 <out T>, 如果安全的话就把 out 去掉,但那就不能真正做到 Tuple 的复用了。
我能断言指定 items[i] 位置的 func 可以接受 T ,因为它本来就是被取并集损失了精度的,于是写了 (items[i] as Con…
duangsuse::Echo
#js 同样是简洁优化,这些就很鸡肋了,尤其是这个eval DSL… 显得非常缝合,但为避免 new Path2D 不得不用 我曾说过「好的代码是横着写的」, 总结下吧,尽管我偶尔写带配置UI的应用,现在我的编程风格已经完全和“软件工程”者不同了 至于好坏…工程界的定义,蛇线驼峰 太基础,没有考虑语序和用途,我的写法会偏函数式点,命名上倾向 Kotlin ,不完全是民科 在我看来,工程界只重视代码的功能,没有顾忌代码的语义和「份量」,所以常常把简单功能写大几百行,以此为“成熟度”,或者觉得C++就必…
#statement 很多时候我不爱看自己的代码,但它之外只有量大后更难读的东西,一些问题想描述都是复杂的,何谈定义“解法”,我一直在努力简化
我就相信不管多难、多牛的人写的代码,都有更通俗的表达法——唉,大佬们总让我失望
如果连《算法》这种英美计科教科书都是不可相信的,我能信任谁呢,所以才说 #Kotlin 是好语言吧,至少它选择相信表达而非智商。 我遇到过天才,但天才尽管悟性好也曾有做得不好的时候;如果说最后他们写出来的东西还是10行能讲明白,如果他们的实践也只是6,7种方法中的一种,而每种方法各都有优劣 ,如果说完成的应用也有无数扩展的可能,我又该崇拜谁呢。
如果天才的语言也不天才,我为什么要全部照搬呢?
几乎每次我研究一个感兴趣的技术,都迭代出3,4个版本,碎碎念全放在旧版、精彩代码粘贴到新版,仿佛细胞分裂时损失聚在一边 。从正常人的视角「重复」肯定是丢脸的事,或者是项大工程,意味着你不懂或不聪明,但谁是生而知之的呢?人的能力是有限的,所以才需要方法和工具完成更多,而有时却被工具所蒙蔽,看不到更「大」的工具。
我为什么要崇拜技术呢?因为「崇拜」它能更好解决我的需求?崇拜天才能让我聪明?
我谁也不崇拜,也谁都不鄙视,只是继续看自己爱的技术; 当我描述,零碎的计算机语言概念和人话并存,而在语言中,名字是最次要的,语义最重。最后我选择了名字即语义,是自9次重写一个框架后我做第二件最正确的事,也是我找不到同道的开始。 自底向上从缘由解读名词,自顶向下靠细分写出程序,而 OOP 或 FP 都只是这种方法论的工具;那些名词,只是它们用途的片面
我相信代码有「份量」,在API在模型之上,「恰如其分」的代码和精妙的文档是绝配,因为短行数!=低功能 。
——只有你不把技巧当特殊技巧,之上才构筑出更有趣的东西;如果你觉得自己或它够牛了,你就止到这了。 就像生物里配平的化学式,已经死了。
天才是不当自己或别人天才的,自满或自卑,与他们的领域和关注点无关。
我追求既普适又不空泛的代码。 既抽象,又易看出用途;顺序位置很重要、符号统一很重要。
人赋予一些事以语序、明确表达里的上下文指代,才能忽略无关本质的多余符号。
强大和技术都是身外之物,人—才是重要的
所以我不想自称程序员了,普通人,编程爱好者有多好
我就相信不管多难、多牛的人写的代码,都有更通俗的表达法——唉,大佬们总让我失望
如果连《算法》这种英美计科教科书都是不可相信的,我能信任谁呢,所以才说 #Kotlin 是好语言吧,至少它选择相信表达而非智商。 我遇到过天才,但天才尽管悟性好也曾有做得不好的时候;如果说最后他们写出来的东西还是10行能讲明白,如果他们的实践也只是6,7种方法中的一种,而每种方法各都有优劣 ,如果说完成的应用也有无数扩展的可能,我又该崇拜谁呢。
如果天才的语言也不天才,我为什么要全部照搬呢?
几乎每次我研究一个感兴趣的技术,都迭代出3,4个版本,碎碎念全放在旧版、精彩代码粘贴到新版,仿佛细胞分裂时损失聚在一边 。从正常人的视角「重复」肯定是丢脸的事,或者是项大工程,意味着你不懂或不聪明,但谁是生而知之的呢?人的能力是有限的,所以才需要方法和工具完成更多,而有时却被工具所蒙蔽,看不到更「大」的工具。
我为什么要崇拜技术呢?因为「崇拜」它能更好解决我的需求?崇拜天才能让我聪明?
我谁也不崇拜,也谁都不鄙视,只是继续看自己爱的技术; 当我描述,零碎的计算机语言概念和人话并存,而在语言中,名字是最次要的,语义最重。最后我选择了名字即语义,是自9次重写一个框架后我做第二件最正确的事,也是我找不到同道的开始。 自底向上从缘由解读名词,自顶向下靠细分写出程序,而 OOP 或 FP 都只是这种方法论的工具;那些名词,只是它们用途的片面
我相信代码有「份量」,在API在模型之上,「恰如其分」的代码和精妙的文档是绝配,因为短行数!=低功能 。
users.map{it.age}.sum()
后缀操作链隐含了SQL和数学的前缀表示法,不同语序适合不同场合和需求,但我始终追求描述间本质上的相同、追求代码与可见应用的相同,从而简化代码-即便很少人能做的干净。——只有你不把技巧当特殊技巧,之上才构筑出更有趣的东西;如果你觉得自己或它够牛了,你就止到这了。 就像生物里配平的化学式,已经死了。
天才是不当自己或别人天才的,自满或自卑,与他们的领域和关注点无关。
我追求既普适又不空泛的代码。 既抽象,又易看出用途;顺序位置很重要、符号统一很重要。
人赋予一些事以语序、明确表达里的上下文指代,才能忽略无关本质的多余符号。
强大和技术都是身外之物,人—才是重要的
所以我不想自称程序员了,普通人,编程爱好者有多好
Telegram
duangsuse::Echo
#algorithm UnionFind、三角分形(精简版)
如果要实现 Set 你会怎么做?每次 add(x) 时去重遍历 uniq() 吗?
现在按数组Array(N).fill(0).map((x,i)=>i) 实现 Set<Int> 。每位与一个索引关联,初始是和自己
当加一对 a-b ,把它们的位置赋上彼此,就能知道在不在同集合内——不行,如果还有a-b-c 咋赋值?
答案是 a->b 关联 b->c 再关联,因此 find() 变成链表遍历后最终同一。然后 add(a,c) 先找这个"b",把它…
如果要实现 Set 你会怎么做?每次 add(x) 时去重遍历 uniq() 吗?
现在按数组Array(N).fill(0).map((x,i)=>i) 实现 Set<Int> 。每位与一个索引关联,初始是和自己
当加一对 a-b ,把它们的位置赋上彼此,就能知道在不在同集合内——不行,如果还有a-b-c 咋赋值?
答案是 a->b 关联 b->c 再关联,因此 find() 变成链表遍历后最终同一。然后 add(a,c) 先找这个"b",把它…
https://tttttt.me/kotlin_cn/25220 #kotlin #go 面向job/task计算称 #concurrent ,和完全平行(如滤镜图片)不同
线程切换 >> 函数调用(没有线程切换下的协程切换) > batch之后的函数调用
>分别对应于代码实现的Dispatchers.Default + 无buffer (如果你写对了的话), coroutineScope + 无buffer , coroutineScope + buffer
Exectors singleThread asCoroutineDispatcher
>wait是指blocking的wait么?没看到channel的代码,但是可以断言里面不可能线程停住等待
>不, 是指协程底层在无可调度时的wait;能看到一半是无锁链表,一半是LockSupport.park
之前和他的差这么多,估计是被调度到一个线程上去了,不知道Default里边的策略是什么样的
bench=repeat(10_000);o=Any()Channel 和调度器 Dispatcher ,在浏览器有 worker.postMessage 和 onmessage
c=Channel<Any>()
runBlocking {withContext(Default){
launch{bench{ c.send(o) }}
launch{bench{ c.receive() }}
}}
//c.close(); launch.join()
var wg sync.WaitGroup;wg.Add(2)defer WaitGroup 在凑齐2项时传输(循环看错位)?其实是用计数看是否有job存活,都Done掉退出时再继续主线程
var token struct{}
c:=make(chan struct{})
go func(){
defer wg.Done()
bench{c<-token}
}
go func(){
defer wg.Done()
bench{<-c}
}
wg.Wait()
runBlocking{//limitedParallelism,newFixedThreadPool,single..也有把 Channel 异步序列变得友好的做法
val produce=produce(Default){
bench{launch{send(1)}}
}
var n=0
produce.consumeEach{n+=it}
}
线程切换 >> 函数调用(没有线程切换下的协程切换) > batch之后的函数调用
>分别对应于代码实现的Dispatchers.Default + 无buffer (如果你写对了的话), coroutineScope + 无buffer , coroutineScope + buffer
Exectors singleThread asCoroutineDispatcher
>wait是指blocking的wait么?没看到channel的代码,但是可以断言里面不可能线程停住等待
>不, 是指协程底层在无可调度时的wait;能看到一半是无锁链表,一半是LockSupport.park
之前和他的差这么多,估计是被调度到一个线程上去了,不知道Default里边的策略是什么样的
Telegram
Michael Corleon in Kotlin CN
其实我也见到 stackoverflow 上有人发现 kotlin coroutine 是轻量,但是并不快…尽管通常来说轻意味着快
duangsuse::Echo
#ce #plt 带步骤的四则计算器。递归逆波兰。22行代码 浅先=`;=;+ -;* / %` 流=(a, _s=[...a].values())=>()=>_s.next().value 切2D=(s,sp0,sp1)=>s.split(sp0).map(s=>s.split(sp1) ) {let t={},k; 切2D(浅先,';',' ').forEach((x,i)=>{for(k of x)t[k]=i}); 符深大=t} 符链=(s,l)=>{let a=[],add=x=>a.push(x)…
#plt #typing #kotlin #java 常见类型系统
从变量/参数的赋值兼容力(即子类成员量)升序:
对函数
而检查期 1,"str" 和
类型的强弱看隐式转换,动静即语法有无分出“编译期已知项”如class结构,类型推导能让静态类型更智能。
现在你已经知道「类型标记」只是仅编译可知,用来
类型的交集&(有
+*类型即分支组合类型,与其配对的是不兼容子类型的系统,那些系统里元组/具名数据类型也算”类型“,但有些奇技(如typeclass函数重载)来解决OOP里有或没有的问题。
A&B 成员集小,兼容力比A或B大,但在严谨的OOP子类派生里,只有 A|B 被用于多态(函数覆盖:多义, Any null?),而交集参数仅混合接口。
感觉有点好笑,我一个看编程语言的,话却越来越少了。 以前很喜欢技术,但感觉越学知识越少了。
从变量/参数的赋值兼容力(即子类成员量)升序:
Any<任何类型<Nothing
,类型 T 比T?兼容力强,因其不含null,error():Nothing
可容任何类型,因后续计算中断。对函数
(Any)->R
连Any都能收,当然是 (Int)->R
,也即 Fun<in T, out R>
,型参值 T=Int 反接受小的 T=Any。是消费-生产 in=?super,out=?extends "通配符",但可直接在写<T>
时指定仅在 in/out 位置,及 Array<out Int>
变量R在两个函数类型里唯一,都来自<T,R>型参列表,对R的每位置归一可推导出R再检查。可以发现,(T)->R
和 Fun<T,R>
都是从类型组合出类型的语法,而检查期 1,"str" 和
Int,String
型变量都是类型(Type.can
haveSubtype),a[0]=1
时问 Array<Any>.set(Int,Int)
是否 params.all{it,i-> it.can(arg[i].type) }
,像在执行一般检查每条算式,能提早报错并加速内存分配。类型的强弱看隐式转换,动静即语法有无分出“编译期已知项”如class结构,类型推导能让静态类型更智能。
现在你已经知道「类型标记」只是仅编译可知,用来
chk(AST.FCall): i=0~nArg; scope["print"].arg[i].can(call.arg[i].type )
的 Type.can(Type):Bool
实例,正如 Python 的 from typing import TypeVar
。Map<K,V>
也是编译期调用,只是class 里创建型参<A,B,..>写法和函数前不同,不是”特殊语法“。类型的交集&(有
where T:A,T:B
"交集上限" )并集|(兼容操作支持俩类型,如 Any? vs Any,AST vs Call If For):子类&父类=子类, A&B=Nothing 、A|B=最近共同超类+*类型即分支组合类型,与其配对的是不兼容子类型的系统,那些系统里元组/具名数据类型也算”类型“,但有些奇技(如typeclass函数重载)来解决OOP里有或没有的问题。
A&B 成员集小,兼容力比A或B大,但在严谨的OOP子类派生里,只有 A|B 被用于多态(函数覆盖:多义, Any null?),而交集参数仅混合接口。
感觉有点好笑,我一个看编程语言的,话却越来越少了。 以前很喜欢技术,但感觉越学知识越少了。
Forwarded from dnaugsuz
(知乎的草稿箱真太卡了
JS的一些技巧都注释了,感谢你的建议;这个确实烂代码写久了自己认识不到难看
其实我觉得,编程是没有水平一说的,就和人讲话一样,知道原因就够了,技巧我实在是我讨厌的(尽管我在用 )。 我不把编程当技术,即便自己是编译原理爱好者
这篇文章穿插了JS和Py ,但你会发现画布都叫 g G,这是我现在的编程规范。
层次感是因为我想教的太多了…… 🤪 在这样的文章引入代码生成。 坦白说只要函数名不滑坡,现在我的代码已经没有规范可言了,感觉我成了自己之前讨厌的人(那种变量名只起1字,也没公式的),现在是因为我需要比代码更高的东西,代码的语义、算法的理由。
我的命名由一个物理命名法(链接“名字即语义”)规范,所以对大家还是奇怪的。一切都是为了语义 😭, 如此我编程时便可仅思考问题,而对问题的符号不假思索,因为我从实现子目标开始就知道一定有某类型符号,和谁1:N等相关,要怎样计算,所以能自由拆解拼合重序代码,不局限于既定形式。
JS的一些技巧都注释了,感谢你的建议;这个确实烂代码写久了自己认识不到难看
其实我觉得,编程是没有水平一说的,就和人讲话一样,知道原因就够了,技巧我实在是我讨厌的(尽管我在用 )。 我不把编程当技术,即便自己是编译原理爱好者
这篇文章穿插了JS和Py ,但你会发现画布都叫 g G,这是我现在的编程规范。
层次感是因为我想教的太多了…… 🤪 在这样的文章引入代码生成。 坦白说只要函数名不滑坡,现在我的代码已经没有规范可言了,感觉我成了自己之前讨厌的人(那种变量名只起1字,也没公式的),现在是因为我需要比代码更高的东西,代码的语义、算法的理由。
我的命名由一个物理命名法(链接“名字即语义”)规范,所以对大家还是奇怪的。一切都是为了语义 😭, 如此我编程时便可仅思考问题,而对问题的符号不假思索,因为我从实现子目标开始就知道一定有某类型符号,和谁1:N等相关,要怎样计算,所以能自由拆解拼合重序代码,不局限于既定形式。
Telegram
duangsuse::Echo
#statement 很多时候我不爱看自己的代码,但它之外只有量大后更难读的东西,一些问题想描述都是复杂的,何谈定义“解法”,我一直在努力简化
我就相信不管多难、多牛的人写的代码,都有更通俗的表达法——唉,大佬们总让我失望
如果连《算法》这种英美计科教科书都是不可相信的,我能信任谁呢,所以才说 #Kotlin 是好语言吧,至少它选择相信表达而非智商。 我遇到过天才,但天才尽管悟性好也曾有做得不好的时候;如果说最后他们写出来的东西还是10行能讲明白,如果他们的实践也只是6,7种方法中的一种,而每种方法各都有优劣…
我就相信不管多难、多牛的人写的代码,都有更通俗的表达法——唉,大佬们总让我失望
如果连《算法》这种英美计科教科书都是不可相信的,我能信任谁呢,所以才说 #Kotlin 是好语言吧,至少它选择相信表达而非智商。 我遇到过天才,但天才尽管悟性好也曾有做得不好的时候;如果说最后他们写出来的东西还是10行能讲明白,如果他们的实践也只是6,7种方法中的一种,而每种方法各都有优劣…
#java #kotlin
>也亏他说得出口,没有受检异常,只会让所有kotlin程序要么发生崩溃,要么catch Throwable。或者,遍历整个调用路径,找到全部抛出异常的地方。
Java先进的异常系统被糟蹋成这这样子,真是人笨怪刀钝。 https://tttttt.me/vvb2060Channel/745
你可以看看.kt的生态发展快、易用好,还是老腐朽 jawa。 kt 的 null?. 其实就删掉许多Throwable 的需求了,要再逼人给 ArgumentError, FileNotExist 这些根本不可能发生的case去写一堆“error prone” “error torrent”(人话: 错误框,方案候补)?那JDK为何定义 RuntimeExc_ ,它先进,为何有人还爱 catch过泛 呢?
异常🌚本来就是非局部跳转-给全局handler,adb log 好了。怪不静态检查,那为何不用 Result? runCatching{} 能满足你说的必须catch才编译 ,直接把fun=catching{}。能写成这样说明你对相关API没有做过预测试,或者方案不够跨平台,就像Google自相矛盾的注解 https://tttttt.me/vvb2060Channel/718
代码自身混乱的七七八八🤪,不能怪语言不守旧。类型必须对算式有利用价值:人不该敲不会执行的字!
#js 就是我们的榜样,Promise.catch.then 里catch{}是可复用的,比之Jawa SEH语法,像拿C与py相比,灵活性爆杀。甚至它标明了哪里会出异常, 而非尾一堆catch{}
😔
Jawa8的类型变量推导算法本是可用在函事var和class量上的,却仍要求写 int x=1; 然后语序上丑到有<T> void f() 比之 class Box<T>。今天到Java11又开始支持var,record类型,List.of和switch->这些 “靡靡之音”了,不爱“努棒性”了吗?
>也亏他说得出口,没有受检异常,只会让所有kotlin程序要么发生崩溃,要么catch Throwable。或者,遍历整个调用路径,找到全部抛出异常的地方。
Java先进的异常系统被糟蹋成这这样子,真是人笨怪刀钝。 https://tttttt.me/vvb2060Channel/745
你可以看看.kt的生态发展快、易用好,还是老腐朽 jawa。 kt 的 null?. 其实就删掉许多Throwable 的需求了,要再逼人给 ArgumentError, FileNotExist 这些根本不可能发生的case去写一堆“error prone” “error torrent”(人话: 错误框,方案候补)?那JDK为何定义 RuntimeExc_ ,它先进,为何有人还爱 catch过泛 呢?
异常🌚本来就是非局部跳转-给全局handler,adb log 好了。怪不静态检查,那为何不用 Result? runCatching{} 能满足你说的必须catch才编译 ,直接把fun=catching{}。能写成这样说明你对相关API没有做过预测试,或者方案不够跨平台,就像Google自相矛盾的注解 https://tttttt.me/vvb2060Channel/718
代码自身混乱的七七八八🤪,不能怪语言不守旧。类型必须对算式有利用价值:人不该敲不会执行的字!
#js 就是我们的榜样,Promise.catch.then 里catch{}是可复用的,比之Jawa SEH语法,像拿C与py相比,灵活性爆杀。甚至它标明了哪里会出异常, 而非尾一堆catch{}
😔
Jawa8的类型变量推导算法本是可用在函事var和class量上的,却仍要求写 int x=1; 然后语序上丑到有<T> void f() 比之 class Box<T>。今天到Java11又开始支持var,record类型,List.of和switch->这些 “靡靡之音”了,不爱“努棒性”了吗?
Telegram
南宫雪珊
又想大骂kotlin没有受检异常。
Adding checked exceptions to Kotlin would be a major breaking change, and as such, would require very strong new arguments in favor of it. At this time, given the experience of many different languages which do and don’t include checked…
Adding checked exceptions to Kotlin would be a major breaking change, and as such, would require very strong new arguments in favor of it. At this time, given the experience of many different languages which do and don’t include checked…
#learn 对我而言,编程并不是「专业技术」,只是“另一种母语”和创作方式,所以我很讨厌潦草的代码
最近一直在打磨一门自制语言的语法, 获得一个较大的成功,居然是把它的OOP术语移植到英文.. 😅
interface Closable
绝句计划把
总之,OOP 的public-private constructor 麻烦真的很大,
我又不认为 Rust,Go 那样把一切打散和到处pub fn, 冗长化 type Item=int32 就算“优于继承” — py也有自己独占的一亩地, 但它足够 "server side" 吗?
对于视频内代码的重写:
唯一能确定的是, 绝句最终的语法和std不会保留冗长且含糊的概念,至少中文绝句不会 (比如 try catch finally 就变成语法函数化+
也不会刻意与py,rb,js 的传统术语分离,一定是小更改换大收益 😋
希望它能打破解释和编译的隔离吧 ,虽然我根本不知道咋做.. 语法风格颠覆的太快
不过我还是很高兴学习过弱类型 metaprogramming ,又掌握了解析和编译原理,所以不必受制于既有的 syntax 和 API,或者对象图框架,而能创造DSL
btw. kt 的 Sequence实现 居然和 yield() 无关 ,居然只是 sequence{} 在创建只读的协程吗
😅而且复制给Array,Set,Str.. 信仰崩塌
最近一直在打磨一门自制语言的语法, 获得一个较大的成功,居然是把它的OOP术语移植到英文.. 😅
事量物例类|公私族组内之前的版本是
fun val data named type|same{,0,type,pkg}
储例判同造|既可未终定
\- enum -when -named made|^,impl{?,??,}
事量物例类虽然不够“面向对象”(obj->data) 了,但实在(英语化)好写不少。 我一直很讨厌 Java 那种八股文式,歪七扭八不一致的语言特质,给数据处理和调试带来很大负担
fun val thing insta class|
储标例况变
data anote enum case var|!,impl{?,??,}
interface Closable
type Closesdata class Pair<out A, out B>(val A:A, val B:B): Serializable
fun close
-named
fun all(:Args<Closes>)...
data Door(name:Str) Closes
made(:Idx)=made("# $i")
^fun close=say("shut $name")
'AB'(get) - Pair(A:A,B:B) Sendtypealias PairOf<T>=Pair<T,T>
'T'PairOf=Pair<T T>这个就对标 #haskell
data=A|B
和 #rust enum Either<A,B>
了'AB'(get)-when Either就体现另一种 #FP 的价值观:定义式先于不可变
A(v:A); B(v:B)
'R'fun way(err:Fn1<A>, ok:Fn1<B>) = when this:
A:err(v);; B:ok(v)
绝句计划把
Var,Type, expr.E
都拉入一等公民,虽然我不清楚怎么做但相信有意义(连scala3都没更灵活的 eval fun: inline arg 还不够全)总之,OOP 的public-private constructor 麻烦真的很大,
我又不认为 Rust,Go 那样把一切打散和到处pub fn, 冗长化 type Item=int32 就算“优于继承” — py也有自己独占的一亩地, 但它足够 "server side" 吗?
对于视频内代码的重写:
事 阶乘(n:数) 数或者更函数式(reduce 和 findIndex)
变数,a 1。
(1~n),[i] a=「它*i」 。
fun Ary<Int> contains(it:Int) Bool
this:[x]
if x==it: return $Y
return $N
'N'fun N`!`=(1~this).Sum{*}(不得不说,绝句的变动太快了.. forEach和尖括号类型都能被删没 (我对那个
'T'fun Seq any(:Test<T>) = this(Sum.from($N): or test(it) )
= first { test(it) }?.i !=NO
对何forall<AB>
的还执着了好久,因为很"函数式"😭 ) , 这两天对于‘带代码’行注释
和事/物 内量的区别对待、C++式iter与可变<T>的统一、 #Kotlin require check 之类“特技”的归一化 也很难抉择 ,所有简写竟都是全新的,而且都能涉及到编译期API)唯一能确定的是, 绝句最终的语法和std不会保留冗长且含糊的概念,至少中文绝句不会 (比如 try catch finally 就变成语法函数化+
试做 接应 皆应
+试:可空 , 之前是 尝试 接迎 终焉
)也不会刻意与py,rb,js 的传统术语分离,一定是小更改换大收益 😋
希望它能打破解释和编译的隔离吧 ,虽然我根本不知道咋做.. 语法风格颠覆的太快
不过我还是很高兴学习过弱类型 metaprogramming ,又掌握了解析和编译原理,所以不必受制于既有的 syntax 和 API,或者对象图框架,而能创造DSL
btw. kt 的 Sequence实现 居然和 yield() 无关 ,居然只是 sequence{} 在创建只读的协程吗
😅而且复制给Array,Set,Str.. 信仰崩塌
YouTube
Why You Shouldn't Nest Your Code
I'm a Never Nester and you should too.
Access to code examples, discord, song names and more at https://www.patreon.com/codeaesthetic
Correction: At 2:20 the inversion should be "less than or equal", not "less than"
Access to code examples, discord, song names and more at https://www.patreon.com/codeaesthetic
Correction: At 2:20 the inversion should be "less than or equal", not "less than"
#Kotlin #design 谈这我就想到,绝句的
就是两回事,避免歧义
get(Idx)T 就应该是方括号
设计语言时要顾虑一致性,不能为了理论优雅,就抛弃语文美感
vs
复杂不一定坏,只要扩展性和性能上有优势
最开始我只是把 py 的缩进给了 Kotlin,但最后,我没有把新手可读性 放在考量里
正则和DFA
说起来对同T 的多个implicit
Scala的优点和败笔同时是implicit。不知道怎么评价,就像你提供了技巧,但没约定好写法
^ val by 可以用 provideDelegate()=ReadOnlyProperty 定义
你没有把defaultFn 传到非 inline 的 fun/var (如forEach {}? ) 里,所以不应该加 crossinline
{cross,no}inline 只是用来禁用函数式参数的ret跳转内联的
好奇在 nonlocal return@ 上, kt 是如何内联的,假如参数内联可以靠IR模板的话
很好奇
OOP是强求了继承关系,或许正常来看
但我讨厌滥用接口trait,应该
感觉py的渐有类型换成全局infer 会更快(? TS 可能有(infer from usage),但是作为IDE功能了
我喜欢用成员交、成员并 表达 union 和 intersection types
java里成员并对接口(&)有点用, 甚至能为 tuple实现Func
—
现在用GPT, 有时感觉编程语言是没必要逐个去学的
但其实语言也能简化问题,方便编程创作;微调时用中文写需求,就很烂
这种有方向特色的创作,是GPT暂时做不到的;目前我只写这种代码
—
#Java圈莫名其妙的不做代码复用,像 Logger 和 Repo 这样就可以依赖注入进去
但变量是应该由
Javaer 的设计模式,除了Builder这种解决语法贫瘠的,都是做了一半, 留了一半给人当CV boy
PYer 虽然又蠢又冗,但至少不会贩卖问题;它解决过的都没有什么复制粘贴和坑
KV<Int Str>
和 [1 2 3].lets:"+$this"
的 Fn1<Int Str>
就是两回事,避免歧义
[1 2 3](Sum)
[1 2 3](Sum{*})
才真正应该是函数调用get(Idx)T 就应该是方括号
设计语言时要顾虑一致性,不能为了理论优雅,就抛弃语文美感
"a".mayAs<Int>?.Str !
(1~9)(Sum{+}.byStep )
(1~100 by 2~101) ( Sum{[a b]a+b } by: it%10 } )
vs
("a" as? Int)?.toString !!
(1..9).scan{A+B}
1..100.zip(2..101).reduce{a,b->a+b).groupBy{it%10}
复杂不一定坏,只要扩展性和性能上有优势
最开始我只是把 py 的缩进给了 Kotlin,但最后,我没有把新手可读性 放在考量里
- 'TR' T lets(:Fun1<T R>) = fn()
fun<T,R> T.lets(fn: T.()->R)=fn()
at N id= +0
val N.id get()=this+0
—正则和DFA
说起来对同T 的多个
fun T.xx
,是可以像Scala那样用 inline class
?Scala的优点和败笔同时是implicit。不知道怎么评价,就像你提供了技巧,但没约定好写法
^ val by 可以用 provideDelegate()=ReadOnlyProperty 定义
你没有把defaultFn 传到非 inline 的 fun/var (如forEach {}? ) 里,所以不应该加 crossinline
{cross,no}inline 只是用来禁用函数式参数的ret跳转内联的
好奇在 nonlocal return@ 上, kt 是如何内联的,假如参数内联可以靠IR模板的话
很好奇
List<get T>
在Go里为何不存在OOP是强求了继承关系,或许正常来看
'T'(T Num Sort)
才是List<Int>的类型但我讨厌滥用接口trait,应该
type Num Sort
感觉py的渐有类型换成全局infer 会更快(? TS 可能有(infer from usage),但是作为IDE功能了
我喜欢用成员交、成员并 表达 union 和 intersection types
java里成员并对接口(&)有点用, 甚至能为 tuple实现Func
—
现在用GPT, 有时感觉编程语言是没必要逐个去学的
但其实语言也能简化问题,方便编程创作;微调时用中文写需求,就很烂
这种有方向特色的创作,是GPT暂时做不到的;目前我只写这种代码
—
#Java圈莫名其妙的不做代码复用,像 Logger 和 Repo 这样就可以依赖注入进去
但变量是应该由
abstract class
来声明 ,不应该留样板代码,否则要设计模式干啥?Javaer 的设计模式,除了Builder这种解决语法贫瘠的,都是做了一半, 留了一半给人当CV boy
PYer 虽然又蠢又冗,但至少不会贩卖问题;它解决过的都没有什么复制粘贴和坑
Telegram
duangsuse in Kotlin CN
在有真子类型前,我还写类型函数(当然这些很无聊,本该由编译器自推)
'AB'type Eqv
- cat(:A)B
- cut(:B)A
!- pipe(:Args<Eqv<* *>>)管<args>
“类型体操版compose()。 函数体无法构造 管<> 类型(来形式证明),故仅调用处受检 ”
!- 管(串:组<类型>) = 串[0]的参[0] 令其,[A]
串去叠(A),[a b] b的参[0]有a;b的参[1]。令其,[B] 类型.参(可同、A、B)。
'AB'type Eqv
- cat(:A)B
- cut(:B)A
!- pipe(:Args<Eqv<* *>>)管<args>
“类型体操版compose()。 函数体无法构造 管<> 类型(来形式证明),故仅调用处受检 ”
!- 管(串:组<类型>) = 串[0]的参[0] 令其,[A]
串去叠(A),[a b] b的参[0]有a;b的参[1]。令其,[B] 类型.参(可同、A、B)。
duangsuse::Echo
🥳 EQ的第一界API集构思好了,它构造DOM的方法,是直接把模板成分和JS值对应: - it关键变量: html`文本${x}`, when(age.as(x=>[x>=100, x>=18]), ["👨🦳","👦"], "👼") - 挂载函数: div(wOSK三要素, ...继续向下), as([abc], x=>bold(x), a=>ul('没有')), ee.组件({数据}.it)(挂载点) - 递归下降$: html(..)(s) 按照s的类型挂载,与 div()(s) 唯一的不同是它不把挂载点=新建div…
效仿 #Kotlin 果然是错的决定。kt爱“术语洗稿”的风格,原来从2017标准库就开始定下了……
幸好,现在的绝句能基于做/到函数
但看起来
总之,开明的语法配上一致的规范,味道真挺不错的
唯独可惜的是, 它们越来越不能“独当一面”了…… EQ的模板与“选中按键变量” 构思好后,整个框架似乎都萎缩了(虽然仔细对比会发现功能是一样多)。当然,越易学就越好
有些新功能一旦成为体系,看起来就稀松平常了,少到让人觉得是否会“不够用”…… 但它们曾显得非常helpful
幸好,现在的绝句能基于做/到函数
1:[x] x+1, (0~9)|: say(+ 1), kv:[k|v]字典
,不加歪七扭八的术语🙉但看起来
|:
这些就很晦涩啊? 不过,绝句是用这俩的重载,取代了所有 for if filter map await Closable.use .."89"==((0~9) {!< 8}: "$this").Str“对单项的filter”
(0..9).filter{it>=8}.map{"$it"}.joinToString("")
resp.isOk or good: A
(x==0) { A }: B “多个参函”
if(resp.isOk()||good) A
if(x==0){A}else{B}
"ab"{!has "a"}? {this}or "bad"现在我轮转设计的四个项目, 都逐渐迁移到了与as/to 相关的体系🥰像
at v = [|key v] ["k"] or: return
"ab".takeIf{"a" !in it}?.run {this} ?: "bad"
val v = mapOf("key" to "v")["k"] ?: return
at now:
x Way<Int Str>.A(0)
y x {+1} {error}
var x=Either<Int,String>.Left(0) //同Result
var y=x.fold({it+1}, ::error)
when(age.as(x=>[x>=100, x>=18]), HTML分支)
这样的变量总之,开明的语法配上一致的规范,味道真挺不错的
唯独可惜的是, 它们越来越不能“独当一面”了…… EQ的模板与“选中按键变量” 构思好后,整个框架似乎都萎缩了(虽然仔细对比会发现功能是一样多)。当然,越易学就越好
有些新功能一旦成为体系,看起来就稀松平常了,少到让人觉得是否会“不够用”…… 但它们曾显得非常helpful
#kotlin #statement 🤔 新身份:Java黑、React黑??😓
duangsuse, [2023/9/30 22:17]
感觉自己最近有点狂了, 看见有人问2D矩区的问题,我的第一反映居然是「这提问不会是认真的吧,xywh加减乘除是简单的吧」
问了下AI,发现这种 Image.crop()也没有直接给出思路或代码,它们变蠢了
应该改改了…… 真的有点奇怪,说不出是哪里错了,可能是反感流行框架不直白吧,但 我不应该教人做事
不过 java awt 确实有点过分,连类似Pair<AB>的模型都没有,许多人都是单独处理 width,height 的,
连 size=2w,1h 这种都要写两个赋值……和numpy太不搭
JDK这些人物理单位都不懂,却搞一堆设计模式,真是在买椟还珠的时候就格外努力……
Android呢,什么
duangsuse, [2023/9/27 15:56]
还是H5
一个毫无意义的区别,让设计师拿来作为特色竞争力,妙呀
duangsuse, [2023/9/30 22:42]
唉,我现在在设计的前端框架,包含一门用于滤镜图/RPC的解释器, 真希望以后就不要再接触JVM界, 完全弱类型好了
感觉配合Java(哪怕Kt)界的窄模型思考,真的很费力。 许多对现实生活的简明抽象、比数理公式更优秀的写法,它们不去收纳整理,反而搞出与其他用途会冲突的抽象, 这样循环互害下去…… 大量学习成本就出来了,总是有新版本能+bugfix+feat
他们根本不懂如何写文档, 有些该单靠demo 传达到的被写成一锅粥,文档主要是原理。但 demo-文档-代码 给它们写成 文档-实现-汇编了……
duangsuse, [2023/9/30 22:50]
py 甚至全局用obj.dict ,这有什么影响。 人的脑容量才是限制IT进步的瓶颈。 优秀的算法和API移植,比8个byte 优化的效果多几百倍
总之对我而已,语言和runtime 只是实现解决方案的工具, JVM是可有可无的,只要它的libs我能自由调用。
一个lib 所提供的价值,等于其 public API+struct 的价值,不含运行时,因为具体实现可以被别人换掉。
库所用的结构是对领域模型的摘要,而API是对应地,实现功能的选项和途径
语言的语法和stdlib,需要尽可能简洁,因为复杂的功能和哲学,往往带来额外的编写时心智开销
duangsuse, [2023/9/30 22:17]
感觉自己最近有点狂了, 看见有人问2D矩区的问题,我的第一反映居然是「这提问不会是认真的吧,xywh加减乘除是简单的吧」
问了下AI,发现这种 Image.crop()也没有直接给出思路或代码,它们变蠢了
应该改改了…… 真的有点奇怪,说不出是哪里错了,可能是反感流行框架不直白吧,但 我不应该教人做事
不过 java awt 确实有点过分,连类似Pair<AB>的模型都没有,许多人都是单独处理 width,height 的,
连 size=2w,1h 这种都要写两个赋值……和numpy太不搭
JDK这些人物理单位都不懂,却搞一堆设计模式,真是在买椟还珠的时候就格外努力……
Android呢,什么
AnimatiableVector
, 向量根本不是动画(卡过点的属性渐变)所专有的概念, 要支持就直接起Vec2这种规范点的名字。 还歧视H5和CSSOM的模型。 编程就是被这群B搞坏的,真正的屎山框架代码。duangsuse, [2023/9/27 15:56]
还是H5
<meta name="viewport"
好,就只有基于dpr的 px vw wh, 然后 sp=rem, @media(device-pixel-ratio:1)
不会因为放大到200% 就蹦出一个更新的单位。SVG里都一样 一个毫无意义的区别,让设计师拿来作为特色竞争力,妙呀
duangsuse, [2023/9/30 22:42]
唉,我现在在设计的前端框架,包含一门用于滤镜图/RPC的解释器, 真希望以后就不要再接触JVM界, 完全弱类型好了
感觉配合Java(哪怕Kt)界的窄模型思考,真的很费力。 许多对现实生活的简明抽象、比数理公式更优秀的写法,它们不去收纳整理,反而搞出与其他用途会冲突的抽象, 这样循环互害下去…… 大量学习成本就出来了,总是有新版本能+bugfix+feat
他们根本不懂如何写文档, 有些该单靠demo 传达到的被写成一锅粥,文档主要是原理。但 demo-文档-代码 给它们写成 文档-实现-汇编了……
duangsuse, [2023/9/30 22:50]
py 甚至全局用obj.dict ,这有什么影响。 人的脑容量才是限制IT进步的瓶颈。 优秀的算法和API移植,比8个byte 优化的效果多几百倍
总之对我而已,语言和runtime 只是实现解决方案的工具, JVM是可有可无的,只要它的libs我能自由调用。
一个lib 所提供的价值,等于其 public API+struct 的价值,不含运行时,因为具体实现可以被别人换掉。
库所用的结构是对领域模型的摘要,而API是对应地,实现功能的选项和途径
语言的语法和stdlib,需要尽可能简洁,因为复杂的功能和哲学,往往带来额外的编写时心智开销
Telegram
duangsuse::Echo
#tool tty canvas #ai 编程失败
>用py实现 sudo hexdump /dev/input/mice -ve'3/1 "%d " "\n"'| for X,Y in lines: 叠加x=0,y=0 并移动终端光标
(很烂而且没有避print换行的坑)
gpmm() { #鼠标光标
stdbuf -o0 hexdump /dev/input/mice -e '3/1 "%d ""\n"'|awk -v kx=$((COLUMNS / LINES)) -e '!/*/{x+=$2/k*kx;…
>用py实现 sudo hexdump /dev/input/mice -ve'3/1 "%d " "\n"'| for X,Y in lines: 叠加x=0,y=0 并移动终端光标
(很烂而且没有避print换行的坑)
gpmm() { #鼠标光标
stdbuf -o0 hexdump /dev/input/mice -e '3/1 "%d ""\n"'|awk -v kx=$((COLUMNS / LINES)) -e '!/*/{x+=$2/k*kx;…