duangsuse::Echo
329 subscribers
3.79K photos
103 videos
573 files
4.9K links
duangsuse技术相干订阅
这是 @duangsuse 与技术有关的发布频道
duangsuse 的另外有 throws 闲杂频道
@dsuset
转载频道 @dsusep
duangsuse 有coding,github,gitlab帐号和bilibili帐号

极小可能会有批评zf的消息 如有不适可以退出

suse的小站:https://piped.stream
ps 另有别名 popf.rip
ʕ•̀ω•́ʔ✧ 🐶🍎🏠生死🐜
(>ω<)岂因祸福避趋之 一鿕
Download Telegram
#java #kotlin 元编程
#kotlin 《progressive》
啊,之前被各路公众号吹爆的 databind 变成 viewbind 了啊,kapt直接变语法树改写ksp了,比我的编程观换代得更快🌚
暴露AST细节乃至sealed dataclass很难吗,哦对javaapt只暴露了定义结构部分的interface processing.Element来允许@Override之类的检查和运行时属性参数值注入

原来databind就是堆@findView.val=o.xxVal 再同步更新吗,因为xml,还真是非常值得起一个名词呢🌚 毕竟html前端都是搞不懂DOM form只会拼字符串的水货

那么viewbind应该是 Angular和Vue 这样的东西了,现在抛弃widget.val的概念,拥抱model/view ,啊不,任意data.val及列表都可以同步到view

我就不明白,根本不是一个世代的东西为啥名字很像
哦对,xml就是一群不懂元编程的人吓唬人的,还什么可配置,所以viewbind反而是回到过去回到最初的做法,那么之前那么多应用都是在干什么?

哦不对啊,View DSL 才是最新的,winform designer.xml 才是最初的,UI都需要设计器,我在说啥啊我🤣

一个小萌新:可为什么 builder.io 就没有专门的设计器呢
因为html是种xml啊
可这不一样啊,你能用webkit设计单页效果,能用View开发View吗,可以啊(Androlua设计器),但是大家都在学“了不起”的“绑定技术”啊🤣
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://t.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://t.me/dsuse/17241 的原因
比如 #zhihu 某专栏的作者
浅尝 miniKanren,传说中的逻辑式编程(二) - 吴烜xuan三声的文章 - 知乎
https://zhuanlan.zhihu.com/p/372280127

如果不是因为科普的萎靡,他本来可以做更有价值的事,这难道不值得所谓的PLT人三思吗? #statement

我到底是一个一个一个什么啊(全恼)🥱
请问下,这种想把get方法隐藏的功能怎么写呢? #kotlin

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…
然后呢华为方舟也是做了个 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{
interface R{void run();}
static R f1;
static public void main(String[]a){
f1="".isEmpty()? ()->{ a[0]=""; } :new R(){public void run(){a[1]="";} };
}
}
javap -c FnRun FnRun$R
""?是为了规避常量折叠。无论多复杂,带><转型的常量表达式 sun javac 都是能执行的..妈耶,在框架限制内你可牛

会得到自带的FnRun.<init>=super() 和 main():
..我们用 #python #code 重构一下字节码表示
//L5 "".isEmpty
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

在非static 方法里 aload_0=this 。在这里 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 {
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
Java8的动态调用不止是新增opcode
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
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();
}

你不能手写 invokedynamc 而只能由 j.l.invoke.* 工具类invoke()时生成,因为调用是在字节码层,不是运行期元数据反射 😒

除了查找函数签名的实现,用户代码不会涉及其他关于计算栈的东西,和最常见的 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
#kotlin 当代 sequence( (0..5).flatMap{(0..it)} == 0, 0,1, 0,1,2 ..
http://www.yinwang.org/blog-cn/2015/04/03/paradigms
“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
#pl 呃,这几天眼睛有点疼,那个网页重构也接近尾声了(目的就是交个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 里只有 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也都是孤立的,并不存在一个”概念“把所有的一切语法和表象连起来。