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

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

suse的小站:https://piped.stream
ps 另有别名 popf.rip
ʕ•̀ω•́ʔ✧ 🐶🍎🏠生死🐜
(>ω<)岂因祸福避趋之 一鿕
Download Telegram
duangsuse::Echo
#android #dev 面试题。上条则是简化版的答案 🧐 仅供参考,可能我解释的太抽象了,涉及一些淘汰的远古技术, 不符合标准答案。 - Handler 基础,Looper 怎么和 Thread 绑定,怎样提高 MessageQueue 优先级 - 进程间通讯的方法,对 AIDL 的了解,对 ContentProvider 的了解 - (根据项目) 自定义 View 的方法和注意事项、事件分发、View 复用 - 写过 demo 吗,什么时候会写 demo - 对 MVVM 的了解,对 Jetpack…
#android #hack #aop 继续,加上奇怪.. 的知识

Magisk 是 Android 版的 Docker (overlayfs),能管理root、去广告加皮肤、安装字体、模拟位置、利用权限骗过 SafetyNet DRM
它让 /boot/initrd 挂载(--bind) /sbin/.magisk tmpfs 来遮住 /mirror/system vendor 树,因此需要TWRP刷zip(和root时一样) 或fastboot刷入kitchen过的原机boot.img

新设备可能不区分boot分区(A/B 切换来OTA),修改内核强制使用 initrd(boot.img) 里的 init(PID0) 程序

简单说,#Linux 启动的传统是kernel解压启动 initrd 内存盘(recovery,Magisk)去寻找真'/',然后 chroot /sysroot /init (systemd,各类run-command,.)

Zygisk 和 Xposed 都是AOP框架,分别拦截和修改 Java android.*/JNI 函数的调用,从而实现对系统和应用程序的功能修改。Zygisk 是基于 Riru 的一个模块,使用 Zygote 注入技术来加载自定义代码。Xposed 是通过替换 /system/bin/app_process 程序来控制 Zygote 进程,使其在系统启动时加载 XposedBridge.jar 文件,从而完成对 Zygote 进程和 Dalvik 虚拟机的劫持。

Zygisk 是 Riru(#cpp .so 函数替换,靠魔改某项linker_PRELOAD) 的免安装续作,开启后不能规避检测,但支持文件/JNI重定向、实现了模块黑名单。 LSP和Ed-Xposed分别支持二者(不能共存)

.internal.os.Zygoteapp_process 的起点,它负责注册JNI、创建 SystemServer(PM,WM,AMS处理的Intent),之后便执行Xp模块
LSP 用 env->RegisterNatives(动态注册版Java_), jni_method_map[T][id][sig].fnPtr 来JNI替换,Zygisk 提供了 {pre(包名),post}AppSpecialize(args)
PRELOAD=libxposed.so 利用 env->FromReflectedMethod(由java查找).{access_flags|=ACC_NATIVE, (Dalvik|ART inlined jmp)nativeFunc=callHooked} 做函数替换

RegisterNatives 本身就能让JNI函数基于jobject clazz 派发,所以比ART hook 简单
FakeXposed 作者的博文

#kt #code
import de.robv.android.xposed.*
import de.robv.android.xposed.XposedHelpers.*

val reg={
val NoPrint={
setStaticObjectField("java.lang.System", "out", PrintStream(OutputStream()) )
}
findAndHookMethod("java.lang.System", cl, "<clinit>", object: XC_MethodHook() {
override fun MethodHookParam.afterHookedMethod() {NoPrint()}
})
}
//assets/xposed_init 写下类名
class My: IXposedHookLoadPackage {
fun LoadPackageParam.handleLoadPackage() {
if(packageName.equals("com.example.app"))reg()
cl=classLoader
}
}
duangsuse::Echo
感觉虽然有些收获,也都是没啥意思的问题…… 面试呢,或许对我这种数学渣就都做不到的吧? #statement 我讨厌这种AI都能写的问题,这些”深刻思考“有什么价值呢? 总是一些算法,让编程变成一种不快乐的任务、变成帮出题人自问自答的”寻宝“ 这些出题人又有多聪明呢? 大众都在润色70年前,世上还没电脑时就有的问题, 而小众又能成什么气候,又如何让他们的沧海遗珠给时兴编程带来价值呢? 如果用《算法图解》那种小说口吻去讲,做一些有弹性的科普视频,倒是有娱乐价值;如果写代码只是为了复制粘贴「能用的东西…
举例, #ts 上有”交并集类型“ (有人认为 hs, Rust 没有子类型所以不存在集合论的,确实如此但 in-out 形变是Racket子语言里也有的,我找不到原文但TRack 是有)
(我一点也不羡慕没有重载和this模块等多态技术的圆括号 😅, 模型的缺失是拿宏手动兼容 a.b.c 所弥补不了的, 就像 F# 的 |> 比不上 xx.let{}, kt 的元组 destruct 比不上 ES6 let[x,y]=P, ES6的解构又不如 Prolog 的 unify [x,1]=[2,y]...

观摩王垠《别再欺负我们读书少》:
- int -> int | bool ->bool 表示的确实是一个intersection type(^),而不是union type(|)
- id(itself) “同时”是int->int和bool->bool,而不是表示它“有时”是int->int,而另外的时候是bool->bool。
- 所以,id(1)一定是int。如果你输入id(True),它推导出的一定是bool。
- 否则,调用id(1)会报错,因为id的类型有可能是bool->bool,不能接受int的输入。调用id(True)也会报错,左右不是人。


但我习惯拿 成员交=union ,成员并=insect ,绝口不提“同时”“有时” 这种抽象说法乃至术语
- int -> int | bool ->bool 表示的确实是一个重载,而不是Either
- id “必须”是int->int, bool->bool ,而不是“可为” int->int | bool->bool。 when(x) { is Int, is Str } 这种情况才是“x可为二者”
- 否则,调用id(1),id(True)都会报错,因为id的类型有可能是bool->bool,不能接受int的输入,或者反之。

严谨性绝对是次于创造力的,况且,含糊的说法对同时使用和实现不利
虽然这些都是小小的细节,但每个细节都注重可读性,随着设计的步进,最终会形成巨大的差异。即便都是用AI,我的实现也会有很多不同
duangsuse::Echo
#py #math 《优雅不是奢侈品》 “如何才能让编程者们相信,简单性和清晰性——简而言之:数学家所说的“优雅”——不是可有可无的奢侈品,而是决定成功与失败的关键因素?” ― Edsger W. Dijkstra,“计算机著作精选:个人观点”,第 347 页。 简单明了的代码就是优雅的代码。这些都是代码中非常理想的属性。Dijkstra 又补充道: “……在软件不可靠性的情况下,最大的成本因素是复杂。 一个可靠的(因此简单的)程序的开发和使用成本,比一个(复杂的因此)不可靠的程序要廉价。” 人们…
#py 周刊
- 《优雅不是奢侈品》
- nogil 最新情报
- #web Django ORM 最佳实践
- Django 自带的JWT 路径验证和登录页
- #ts 阮一峰 入门, 纯JS入门

- #linux #rust Nush: 不是 Powershell
- #js npm依赖图
- #ai #tool realsizer4x 超分辨
- #rust pixi add cowpy 强化pip
- #ui Toga: 跨平台的 TkGUI

- #ml Viberary: 开源书籍检索引擎
- Khan 为何从Py2移植到 kt,go
- #parallel 用asyncio分享查询,防止缓存失效时并发卡爆
- #plt Rust vs Idris,Zig: 渐强类型的解药 #1

单进程 cron
from apscheduler.schedulers.background import BackgroundScheduler

cron = BackgroundScheduler(jobstores=sqlite)
.add_job(print, 'interval', seconds=5)
.start()

并行 multiprocessing: #2
with mpire.WorkerPool(n_jobs=5) as pool:
results = pool.map(getFiles, range(10), progress_bar=True)


- 修改语法ASDL,实现 map( (x)=>x*x, [1]) [Parser/Python.asdl] [30行实现]
- 奇怪的for赋值, 魔术方法
from xx import*明确化:设置好 xx.__all__ = [exports]

实现 lazy load:
importlib.import_module

⭐️import pyforest 自动导入np,pd 等变量
#code 修改语法 __import__('cv2') -
from lazy import cv2

import types,sys

class lazy(types.ModuleType):
def __getattr__(self, mod):
import importlib.util as _
if None==(r:=sys.modules.get(mod)):
id = _.find_spec(mod)
# get it inserted into sys.modules.
_.LazyLoader(id.loader).exec_module(r:=_.module_from_spec(id))
return r

sys.modules['lazy']=lazy('-L imports')
— 仅供学习,import 语句本可以是局部。 (GPT怎么变蠢了
#ts
#1为什么静态类型的C,Go,C++ 不是弱检查 就是太复杂

代码练习: 不需要 type WTF<> = 就可以检查 htmlTag, funcPipe, nthArg, printf("\d") 等调用的类型

int[10] 的实质、 #Kt 类型推导的原理
duangsuse::Echo
#py #math 《优雅不是奢侈品》 “如何才能让编程者们相信,简单性和清晰性——简而言之:数学家所说的“优雅”——不是可有可无的奢侈品,而是决定成功与失败的关键因素?” ― Edsger W. Dijkstra,“计算机著作精选:个人观点”,第 347 页。 简单明了的代码就是优雅的代码。这些都是代码中非常理想的属性。Dijkstra 又补充道: “……在软件不可靠性的情况下,最大的成本因素是复杂。 一个可靠的(因此简单的)程序的开发和使用成本,比一个(复杂的因此)不可靠的程序要廉价。” 人们…
#kt #design 刚才审核绝句 句级跳转&主语域时,意识到 break continue 这些必须和 if 搭配使用 ☺️,以及
- 因为使用 (0~9):[i] break i==5 的语法函数化, break n 必须=return^n*2+1^ ,就像 this=you^0
- tailrec 是 at xxx=let: return^0^ any 里的(ret赋值&break) 的平替

fun IntRan.forEach(fn:(Int)->Unit) {
var i=first
do { fn(i);i+=1 } while(i<=last)
}

- Rn<Int>.`|`(:Fn1<Int>)
at now: i A
let:
fn(i)
loop(i+1): i!>B //i<=B

// AI的编程效率高于补齐,阅读速度上还在用 map-forEach, let-apply 这些的话是不够的
((0~9) : +1) == (1~10)
(1~10)|: [x]
say(x-1)

👀 过滤操作时 (0~9){>5}: say(this) 是绝句里单项和列表通用的搞法
"a arm bar ada".Sep.firsts{it[0]=='a': if !this{say("End")} } 则关于break,因此本应抛弃单层循环的break
我勉为其难地支持了,但写法必须比较丑

- Str find(sub:Str) Idx
at N=sub.Cnt
(0~Cnt-N):[i] //N=1,则 i=0~iLast
(0~~N):[iS]
breaks^1^ this[i+iS]!=sub[iS] //也可以每次iS=i 然后blabla.. OIer 日常的面条代码?
return i
return -1

- 文 找(:文) 针
在N=文的计
(0~计-N),[i]
首否(文、位=i) 去路,回i。
回-1


- 字串.找位置(sub:字串): 数 “降质版: 易😋语言”
变量 N=sub.长度 ‘’它可变吗
(0~长度-N)去对所有:[i]
(0~<N)去对所有:[j]
跳过^1^ 我[i+j]!=sub[j] ‘’它真的ijkPlayer,我哭死

“如果 本对象[i+j]!=sub[j] { 到循环尾^1^ }”
回i
回-1

易语言化还不够给力,这个翻译得一点也不爆笑 (虽然但是,吴涛对Winform和计绘是比大部分人都资深 😁

- if else 是函数,里面不能写 break ,只有 loop: when: 是真正的流控
但语法函数化的好处多多, 通过提高语言一致性,能方便AST匹配和宏、节点图形化编程 ,允许顺语序的去路() 等块函数

虽然,代价是丑陋的写法显得丑陋 ;但语言变漂亮就够了 🥰
duangsuse::Echo
#blog #meme 看到易语言还在VB++ 的范式旁徘徊 😅,并且觉得编程语言 是种必须特色和备案的「核心技术」… 我想复刻下这2007年文章的口吻: “绝句.ju”十分钟入门教程 作者:转载必须注明出处 亲爱的朋友,您愿意花十分钟的时间,来了解一门全新的编程语言“绝句.未公开”吗?(搞笑向 btw. 很难想象标准库与ES7接轨,拥有函续、不/可变数据集、流/叠加、双主语的绝句,还能用“合规”的记法支持VB7时代的“正统中文编程”👀 - 起点 将123写到屏幕 100.123:[x] …
#java 看到一篇维基挺有趣

'T'物 泛型类
造于 此刻,
值 可变<T>
- 读=值
- 写(:T)
值=它

- 方法1
泛型类<数>,
写(5);说(我去读)
- 方法1
泛型类<N>,
写(5.5);读() (说)

绝句不使用“元类”。 T同名例、T 的变量域是隔开的(T上没有“静态”),类型保存在TYPE里

物 值() .地址 “函数,管道 等对象不能是key”
- 特征码 数
-
=(:值?) $YN

类 地址
- 文 文
同名例 TYPE
在 词: 名动词表
在 物名="值"到"ju.Any"

也支持trait (代理基类,扩充接口)
'T'(T 两序) 物 盒(:T)
'T'物- 盒 作 两序
-| 较(:盒)=它 去较(盒的它)


如果 #kt 支持的话应该是
data class Box<T:Comparable<T>> (val it:T)
fun<T> Box<T>.as() = object: Comparable<Box<T>> {
override fun compareTo(box:Self)= it.compareTo(box.it)
}

对我而言,编译器是“做语言”的手段, 可是一些人觉得,编译是“语言”存在的目的... 他们设计语言和框架,是为了让自己新学新想的奇技淫巧跑起来, 因为那些破事如果不能“攀附上”某些实际问题,就会暴露其设计性的廉价(

相当务实!他们大概和最新款的 Cortex-A9 SoC 很聊得来吧。走GPT的路,让计科无路可走… 😄
duangsuse::Echo
#zhihu #PLT 又看到有趣的中文编程设计 ,做些科普。 👀 1.打这些太极 还不如就叫真假,另外,加语法糖并不是以混淆基本语法,以编程的一致性为代价. PHP,Ruby,Py2 和VB已经玩烂过这套“大小混写”了(你怎么不用神奇GPT编译呢?) 2.子类型对应的是强制兼容,而非隐式数值转换。 进制只是表示法,SQL那种类型只是验证位数 你说的不需要看(隐式新建类型变量)、运行时可见,Haskell、Kotlin也支持,但你对连 List<T>,T->R 都还没懂的人弱化类型,就利于他们学用新接口了?别把隐类型当成无类型…
#statement #kt 反思: 数据绑定DSL val xx by int() default 100
> int()返回一个可读(写)变量 ,同时接受"xx",也能实现 lazy{}懒加载

obj HTTP {
val maxReq by int(or=100)
}
怎么样

感觉好鸡肋:这其实就是一种JSON按类型绑定啊…… 只是序列化器没支持而已

有时感觉弱类型真的挺自由的,除了大部分 str,int 就不会写什么多余的声明
你说既要验证 data classes ,反射库又那么鸡肋,还没有官方的模板代码生成器…… 2017到现在连个能比 argparse 的CLI环境绑定都没有

稍微把反射库用好一点,就不会要写这些定义DSL
(但是又不要靠 @VarName("wtf") .. 总之就没绝对优美的封装办法

duangsuse, [2023/9/5 16:49]
稍微想了下,把类型和定义当成元数据,是可以避免 @Default("wtf")
js
HI(class xxApi {
'/index'(){}
'/user/$'([id], {nameMatch}, resp) {}
})

kt
data EnvVars(maxReq=100): Mapper
Map.load<EnvVars>(environ)

这样可以避免注解,其实就是靠查参数表;所以JVM反射和编译期生成可以取代绑定DSL

duangsuse, [2023/9/5 16:55]
强类型真的挺鸡肋, 手写签名只是为避免强转开销? 框架却不能规范和利用这些定义信息?
真的道阻且长啊

听说 #Rust impl<T> List<T> 就是把类型参数当kwarg造成的

我了解了下:关联类型不是只在传参上像kwarg,也不是为方便override,而是做了类似 FnOnce 的保证

1. type R : struct = 1:1,一个 struct 拥有关联 Trait 的唯一 impl
2. R变量不能被struct或fn新建

因此 fn distance<N, E, G: Graph<N, E>> 里G的约束就不必写了,而是替换为 G::N,G::E

还是很鸡肋啊.. 为了三行碎代码😐,为了一个保证而新建语法,破坏语言一致性
即便把泛型改成按名传参 -'NE' Graph.distance(:N,:N) 都比新增语法要一致
是Self类型的一种扩充,因为 -'N'(N Sort) max(:N,:N) N 无需解出N以外的变量

duangsuse, [2023/9/5 17:13]
是不是懒得升级编程语言的社区生态, 都开始急着加无工程意义的特性了

这种能靠推导出事情交给GPT不就好了…… (编译期性能就拉倒吧) 为框架和社区干点正事,多研发点教程文档不好吗
编译这种事情没啥价值啊, 如果数据类型、class这些定义结构,只方便编译,而对框架是负担,那对开发者和用户也是种反模式吧

我是希望Kotlin能像Python那样发展的,但看来py也有不方便大项目的地方

py最近加的match都不是在types上的扩充,我想kt可能是语法太丰富, 但是这个API绝对不够用啊
duangsuse::Echo
这是一个完整的Java式类型系统,支持泛型。 class List<T>{} 的语法对应Fun(T,ID())的数据。 Unit,Fn可视为不属于Any -'TR' Ln<T>.as(:Fn1<T R>)=Ln<R>(0) 也就是对 Arg((Fn),TR) (赋参数),深度遍历到 Ln.To,T.to(Int).. 就知道T具体是啥(还要支持map{map{}}..) 在T未知时结果是 List<R> ,但要生成代码时R一定被固定在Arg。这类把Var作为值的算法叫“合一 unification”。这是关系式(而非“顺序”)的,…
#FP #math 的一些 #statement
#tool html bookmarklet data:text/html;utf8,<body ContentEditable>

—10÷3=3…1
被大佬建议写成 =(3)3+1 即m=qn+r (r<q)形式的“短除法” ,理由是...没交换律
“理论家布尔巴基有个笑话: 1+2当然是2加1,因为整数对加法构成阿贝尔群”

当然,纠结这些除和除以工程意义不大
ax+i=b; x,i=divmod(b,a) 的可变量元组数学里可是没有。函数只是“关系”,没有sympy那种条理分明的元编程化简法,py那种无论匹配或访问都易懂的“类型化数据”

a%b 余数在进制计数法,KB MB单位,乃至红绿灯🚥 ,猜拳、[123]*3重复 里都可以用到,四则符号的推而广之是很方便的
但GL的vecM和距离函数, 对偶的cos atan2才算是真正的「函数图像」

对软件来说,值之间的关系、算式的归类、代换(元编程) ,都是值得思考的,这远比重复流行的技术栈重要。 形式化的语法,正是物理和编程比数学广泛的一点

— 纯函数的不可变吧…… 不是类型上'final' (btw. KT-override class 理论讨论)
意义真的不大, 无非是把堆里的变量放栈上来重赋值,或者栈变量换伪递归,拿能够DFS的写法却只做列表处理, 有什么用…… 又麻烦又慢 😓

变量关系式编程(LP)里, 函数式的 Memo f()=x+1 可以直接表达为 f(out y,x) 的细粒度重计算,解构时也一样! 不仅不存在“赋值”,也不需要那些纯函数的过度检查

一些人觉得 React是什么FRP,functional响应式 。但其实把可变数据,理解为含Var的不可变, 比纠结于List纯不纯好玩的多

类型姑且还是对心智模型的硬化, 纯度这些可都是虚无缥缈的风格格调了。有趣的软件未必靠FP来写。某些函数式lib的样板代码不比rs,go的少 ,代码质量只能是看人,是否憎恨冗余

—我想用 for()await varAssign; 替换组合力很低的 for await(x of {async*f(){ }}.f()){} 异步迭代器,也方便RPC/跨语言 的对接 #PLT
异步流每次next()只是Promise,但换成两个async()赋值--单监听, 用 var.Saw.to(x=>新值流)+AbortSignal 更一致

async()=> 的实现要调用 yields={*f(){ res=yield }}.f(), s.next(1) 里f的yield会把值和'自动回调'赋值到s.next,交给调用方调度。throw也可以直接next回调链表(CoroScope)里有catch的那层。
Iterator显然只是调度的一种特例,是把i++等流控 继闭包地从栈分享到堆。不能牵强地把等待恢复、迭代混为一谈

在ES5里,可以用一个 co(asy()) 来遍历 task.then(next) 并搭配 yield* tasks(下级)#Kt 协程则是直接把回调交给timer()等待,无遍历:

#js #code
wait=(n,ret)=>setTimeout(ret, n*1000)
we={*f(co, ret){
setTimeout(co.nt, 1000); yield //函续已经交出去了,现在该返回 就像f只是登次记
wait(1,co.nt); yield
alert('2s'); ret()
}}

_await=(f ,c={},s=f(c,()=>Job完成))=>(c.nt=x=>s.next(x), s.next())
_await(we.f)

把f变成大switch并不难,但Lua,Rb,Py依然在用运行期魔法实现yield:

we.f=(co)=>(co.nt=()=>{[ //先把f(yield)外提为x=
()=>setTimeout(co.nt, 1000),
()=>wait(1,co.nt),
()=>alert('2s')][co.i++]()
if(co.i==3)co.ret('like,co=Promise')
})()
we.f({ret(){'此谓调用约定,ABI'}, i:0/*func*则会等待1次next*/})

把co暴露给调用方更像JSPy (缺点是要由main调度then(next)),而把co暴露给下级 更Kt,Lisp (虽然更像回调, 但太隐式, 比如yield(x)需向Iter对象赋值 脚本没这作用域)
到了OS这级,键鼠事件,异步只是赋值+触发回调

—翻译一下, suspend fun f() =f1()+1

首先f()要是一个闭包(即 匿名class .new ),kt,Java ()->会自动实现这一步
然后,f1接受第二个this: (Int)->Unit 实现其return 。这就是JS的Promise.then 。你说的local vars 就是指 Promise or Continuation函续 or Async状态机(大switch) or Future..

f的执行也不能卡线程栈了,它也要靠回调,比如runBlocking等待其他Thread的信号量,或者在IO,Main等 Queue(函序) 调度

这么说,call queue 和单CPU多线程本质上都是分时复用,只是设备中断/SIGTRAP 被改为更高层的函数回调,CPU cycle 换成主循环(监听轮询poll)。 因此王垠觉得Lisp比C更适合写OS

Go,JVM,Ruby,Lua 的 stackful 模式允许不标明await 且仍支持返回值,而基于CPS回调的协程则兼容性好
不能把await 调用理解为有返回值的多进程,相反,函数自身是消息队列内的Task(即线程,可sleep),才能去"非阻塞"await

语句就是种顺序表达式, val x=1; f(x,x) 本该也能写成 f(x:=1,x) ,往往只是外提为val,所以await()就像 f(a?.let{return} ?: b) 是可以的

还有coroutineScope, sequence, select 等复杂的结构化信息。 这样能实现大goto(call/cc) 的功能,比如直接resume给某个 caller 的 catch(IO Monad) ,或者 yield 到 gen .next() ,DFS防止栈溢出等

yield的一种用途就是遍历Rx流,但它们生成的流却非异步(尽管它能"push"无穷项)。 另外我觉得RxObserver=next 比async yield 更合理

—「值和引用」别扯到C上
栈就是“非常容易做GC”的堆, 只因为在堆上就叫ref不算值 是不太定义式的,这暗示了 N2(x,y) 这样的数据“不该可变”-即便它说了xy都是变数
别把JVM当成C++的框架。调用栈是内存的一部分,函数值和对象都是“栈转堆”,return在内联后只是赋值;goto,参数并不配特立独行

copy和ref 的区别,只应在于后者是Var(mutable v:T)。 含var的struct也能纯复制,List也可以存栈上(调用在栈顶时,可以追加 int a[num])
只是对集合/事件/闭包等应用层共享,就必须有GC,Rc 来修剪对象图

绝大部分val=struct 的实现依然是堆内共享,与内联函数相当。只有int这样机器mov的值不用传指针

—编译和优化
>AI没答到点上。 我觉得synchronized和Mutex有什么区别, 就是取消 object.wait()才隔离出的

>竟然是让 withIndex() 驱动 get(it).. kotlin-stdlib 里的一些实现是自己在 for each 外 var i = 0 计数的……
智障,就像标准库不写 val x get() 写 fun getX
自己破坏自己提供的特性

>list set stdlib 里的这些集合库的indices属性都有优化
我说的是一般的 for (a in list) 优惠成 indexed for loop 去掉迭代器这种

都能让你手动改写法优化了, 要编译器和有两种IR的虚拟机是干什么?

编译器已经是优化了,虚拟机还要JIT, 结果应用层还是不能满足……
是啊,我就是觉得这种现况很可笑。kotlinc 还特别自己弄了一个内部IR,不知道是用于翻译goto 和协程还是啥

编译优化全都是不可见的, 你也不能知道llvm,ktc 执行完优化是啥样子,非得反编译
当然,clang,llvm 是可以导出IR的,但许多优化用的表示IR层级太低,正常人看不懂

这种情况的解释,就是IR的语意不能用语法来保存了, 但其实 loop/重复算式的外提,并不会破坏程序结构,甚至DCE都是要由IDE重做一遍

玩编译器那帮人根本不懂如何做交互式编程、图形化框架。 这一点 dnSpy 一个反编译器都比90%的编译器做得好
更别说同时有TUI,Qt,Web 三种界面,支持无数种bin格式的 radare2 了
duangsuse::Echo
#zhihu #PLT 又看到有趣的中文编程设计 ,做些科普。 👀 1.打这些太极 还不如就叫真假,另外,加语法糖并不是以混淆基本语法,以编程的一致性为代价. PHP,Ruby,Py2 和VB已经玩烂过这套“大小混写”了(你怎么不用神奇GPT编译呢?) 2.子类型对应的是强制兼容,而非隐式数值转换。 进制只是表示法,SQL那种类型只是验证位数 你说的不需要看(隐式新建类型变量)、运行时可见,Haskell、Kotlin也支持,但你对连 List<T>,T->R 都还没懂的人弱化类型,就利于他们学用新接口了?别把隐类型当成无类型…
#FP #js #kt 今天来桶白象 🤍🐘
>https://www.zhihu.com/question/624728280
"匿名递归,我们调用的是另一个函数。没有什么问题"
发现一个逆天的回答, 直接把调用栈函数理解为匿名+纯函数了,想递归还得加惰性Proxy..
>https://zhuanlan.zhihu.com/p/659387315
看到个同样逆天的

这个Proxy也能做,
argf=(rec,f=rec((...a)=>f(...a)))=>Object.assign(f, {of(F){f=F;return this}})
Y=argf
Y(f=>x=> x?f(x-1)+1 : 0)(10) // 多测试这条

argf(f=>x=> f(x)).of(console.log)(10) //而且还可再定,避免把arg0=self 到处传。

递归的好习惯是只思考1层-勿判断子项,Y都没做到这一点
Y=\rec. (\x.rec xx)(\x.rec xx)
Y=rec (\x.rec xx) (\x.rec xx) //注意, \x. 只是单个参函数
Y=rec Y
//不动点, noOp,id

\x.xx 在调用后把自己命名为x 交给自己(它就是对称形状),因此使用f就等于 f(f) (x)
看着很好但依然要把 rec(rec, x-1)+1 里的rec放堆上,但Y的意义就是「在不允许堆变量时,用传参实现可变」啊?

返回自己是伪递归,是循环,但 f(f)(x) 最后不是调用f,而是又生成一个f,只因你不能靠赋值,补充如何跳回自己这里(就与编译原理不一致了)

Y只是要证明lambda演算(S-Expr 的纸笔计算)可以递归……
Y = f => (x => x(x)) (x => f(y => x(x)(y))) //y=Proxy
为什么流行实现,和理论不同? 试试直译:
Y=c=>(f=>c(f(f)))(f=>c(f(f)))
//其中 (f=>f(f))(f=>f(f)) ()()()..这种"fork炸弹"会栈溢
请把 f(f)惰性求值
Y=c=>(f=>c(x=>f(f)(x)))(f=>c(x=>f(f)(x)))


不过 ycombinator.com 确实是因为这个「组合子理论」(某种Brainfuck🥰, 异于定义式编程里的"可组合")起的名
众所周知,爱讲众所周知都是别名大师, 他们的理论与既有概念间是隔离的,因此你要学习的内容就如 node_modules 那样多。 聪明的做法就是,先搞自己的,再兼容别人的
#statement #kt #dalao 为何退出..
>可惜JDK没有 @android.webkit.JavascriptInterface

不然小dataobj用html form 应该挺好改
我的天哪 frame.add(this, BorderLayout.NORTH)
AI真的get到我说的apply{} 是咋回事了吗,反正我是很讨厌语句式UI

我还专门写了个编译期 append框架弄Tkinter
现在想想,还是用DOM吧,H5最有前途

duangsuse, [2023/10/19 18:38]
https://github.com/duangsuse-valid-projects/TkGUI/blob/master/tkgui/codegen.py#L162
大概是拿DSL模拟py的obj访问和调用 ,然后把值代换回变量名

>编译期 append
^ ice1k 大佬决定推群,因为怕被回复
我不是想强调我做过什么 😅

这种东西现在看起来也很屎
我只是注释,因为你提到了这个问题
实现方式,对我而已言是为代码桥接的。只要语法或心智模型一样,就行

当年写的东西,虽然很烂,但当时也确实没想到更好的

duangsuse, [2023/10/19 18:42]
那这么玻璃心。我有啥办法呢? 我一直在这里,我不需要与任何菜鸟隔一层 阶 级 😓
真是对自由讨论非常不友好的, 连tg都没考虑到的情况
这个人能看到我的消息,我却不能回复他

而且不是静态检查的不能, 是圈他以后,他会抛下一句话退群
检查类型了,但没完全检查

不过,tg的黑名单真的有待改进

isekiのChannel, [2023/10/19 18:47]
你的思维呈现极端的跳跃性

duangsuse, [2023/10/19 18:48]
哦,不就是否决了你们的一些落后观点, 就说我捉摸不透了
>是啊,我们这边实在跟不上您的思路

我是要用这些知识真正做事情的人
可不是像你们这样,拿着,然后不说也不用

duangsuse, [2023/10/19 18:50]
你们今天懂的,或许我不懂
但我懂的,就一定让它变成儿童编程一样的复杂度

你们觉得不严谨,反感,我无所谓
我非常乐意和冰封大佬在一个群里
但这次是他主动退出的,我没办法

法不可知则威不可测, 他一直在回复我,我以为他又正常了呢

—不过当年写的,确实涉及许多不相干的东西
本来可以用确定性较强的 for x in: constEval(x)

我却创建了一个能uneval() 的“虚拟树”
不过对DOM树,这些语法糖就都无所谓了

duangsuse, [2023/10/19 18:56]
不是的,在Tk 里支持XML式的EKV树,需要手写遍历

我是想纯生成append代码,也不要有调用栈,就是节点ID和配置+子级
所以在调用时,+值->名 替换的副作用,刚好能输出代码,但其实不够优雅

现在我也没想到其他做法,但设想的 js evalFun 对纯常量(split,.)的0开销还是做得到

duangsuse, [2023/10/19 19:04]
另外冰封也写过C-binding + View DSL

他自己应该也有些UI框架,有别人做了 java DSL ,初次提起TkGUI 当时他就回复我这个

对我而言,这几百行代码的份量,相当于刚才我一句话里的语意, 甚至还不如,因为那时我不知道 form input[types],被不广泛的心智模型带偏了

今天的我,搞不懂为什么你们以无法被解读的代码为傲
你们未必能完成最初GPT能实现的目标,却完全丧失了「软件工程」 的优势。你们做的能用的项目,和那些抽象的概念间是没有一致性的,它们不代表你们编程力的成长。 这种习得性的正确记忆,难道能称为懂理论,或者有思想吗?

元编程也不过是编程, 类型推导也不过是「变数关系式DFS编程」, 你把编程语言当问题,只会在正事上一事无成

duangsuse, [2023/10/19 19:10]
不要管了,实在不行就拒绝用Logger
Log4Shell (CVE-2021-44228
24 November 2021; 22 months ago
#learn #js #kt #java 🧵 📥
借机聊下线程、协程间的对应性,以及UI/UX应用与单次脚本间因何不同。(全栈)

调用返回要靠 -Xss 指定大小的线程栈,数组
调用异步要靠 ret() 参数指定的回调栈,链表, 也可以封装为 new Promise((ok,err)=>ok(0)) 。内部执行前都要传入then步骤,但不需要看调用栈
你可以把异步栈保存到[]{}里按需执行,称为调度。协程(async stack)和linux调度器的区别,仅仅是后者能跑死循环(分时复用CPU)
总之 线程栈=调用栈,异步栈=回调栈。

ps|head -n1 这样的管道write() 其实就是yield。这时read()不会等待/dev/disk/的CPU.IO信号,而视ps下一块缓冲的bytes (C对象的Channel)
信号,不是死循环轮询poll,它看注册推送push。不过Looper,HTTP-epoll请求响应 这种ddloop(detect-dispatch) 模式会混合两者
本来,为了不卡死主线每次IO或延时也要 launchThread{b=f.read(); rest(b)} 。封装为 f.read(回调) 就异步了:线程无关
生成器, yield(x, Ret) 会保留首次调用偷偷建的状态机Ret,第二次next(v),调Ret(v如异步结果)后即可返回x。 asyncFn=(args, op=0, Ret=(v)=>switch(op++){} )=>相当于协程对象

主线程sleep()往往要卡死UX,但 yield ret=>setTiemout(ret,1s) 却会立刻返回,同时允许ret()上文切换到其他线程池(ddloop,scheduler)继续执行
造成以上区别,是因为push比poll有普适性,它跨CPU地执行同一个函数,且有event/flow based 范式帮助模块复用。libuv和DOM就是对os.read,sleep.. 跨平台的线程池优化

既然如此,好像有UI+IO两个线程就够了,你干嘛~要多开线程
上文切换,只因,为能更好地压榨多核线程池
DOM代替大家做了划分,为多线提供了内存安全的Worker,但kt,go,py里暴露的技术细节有点多!

线程和 asyncio/suspend 相比有何劣势? linux上进程内是创建慢的进程组(fork)。在不调用OS资源时,永远使用协程"套娃"能减少到内核态的上文切换和内存消耗。像线程池存在的意义,就是免线程创建http连接等单任务
需要mutex锁的独占性资源,用协程读写更节省轮换
单协程轻量到1个回调就能保存,并发控制如 join(coroutineScope),go select,channel 可以用Promise.all,race,postMsg来"阻塞",因为它提供了进程模型所缺少的返回值。
线程即共享内存的进程,无需手动封送(marshall RPC)就能互调用,而json本意是保存会话(对象树)。 如果内存会话和机器都要隔离,就需要 Proxy(by=cookie酷卡/fd句柄) 验证对象API权限了
通过句柄而非密码访问API,是因为句柄能定期吊销,也便于审计。代理有时叫注入,Mapper,绑定

那么jdk19 虚拟线程 又如何? 有100w级的并发1s内完成的低开销,类似py的GIL
但绕过JDK的IO走 JNI Unsafe 读写文件或网络是无法实现异步调度,未实现 suspendCoroutine{it.resumeWith(Ok(0))} 这样的yield的扩展性
var vs = Executors.newVirtualThreadPerTaskExecutor(); //Executors.newFixedThreadPool(200)
for(var Y= new int[]{0}; Y[0]<3;Y[0]++)
vs.submit(() -> { int y=Y[0]; try{Thread.sleep(java.time.Duration.ofSeconds(y*1));} catch(InterruptedException e){}
System.out.print(y + " "); }).get();

最后,再了解经典的「并发模型」 就能读懂90%的企业级服务了

- ForkJoin,MapReduce 如把文件预分块(shader) 读http区间多线程下载
- Actor 直接按函数参数,自顶向下来分块(RPC)
- CSP 是上面说的多进程,靠 Channel<in T>, chan<- T 递交任务,流式的 make -j8
- 线程&锁 互斥资源不能被linux多核调度改乱套了,所以得加锁(synchronized)
#learn #kt Benny霍评论区
协程 async。自动传回调、var都打包到其class因为,比如传给sleep()后自己要return。协程对象就比()->闭包多留个switch(nthStmt){}

把sleep()外提为赋值语句,以保留和恢复调用栈而已,linux单核调度多线程,甚至你调用IO时为了鉴权,也会这么干。 cat|head 不就会await您的键盘吗? read()就会suspend 1个C语言的“有栈”协程。
之所以要async,只是想节省pthread_create,因为你要拿mainloop去poll(定期/卡http的轮询) 触摸屏事件,设备资源是独占的。这和内核驱动(/dev/WebUSB) 才能导致死机蓝屏是一个道理

如果系统,比如Web APIs吧,只提供回调而禁止while(1),哪怕只支持epoll(查看监听)/select(poll多项),就根本不存在线程一词 -就像C里你并不知道read()本质上await在pipe前“生成器”的write()
--也有人叫它yield,那是因为我们不能靠return写入“文件变量”、不能重赋值函数参数以返回多个值.. 为此jspy还发明了“async*()=>生成器”..
完美复刻UI层State(val).onvar[]的轮子呢!可惜是难用难复用的阉割版。

VSCode只加两个js线程,就能运行得很稳,这难道不是App设计的常态吗?难道那些小程序比code更“架构”?
至于免锁或基于资源.transferTo()的多线程,WebGL/numpy/MapReduce(ForkJoin) 不需要重造OS 1Dispatcher:N Continuation(该叫class CPU: ()->isFinished吧)的轮子配什么池化,就能实现前后端们无法想象的性能提升。

ES5的 yield cont=>setTimeout(cont,1s) ,由awaiter链接timeout和g.next,已经是免编译协程API的巅峰了,Promise.then 只是省得你传cont回调。 当然,timeout也可能返回cont=> 所以then要能接受async()

另:JS是视 fetch(u,{abort:Signal}) 取消任务的,我不认为app里会需要一堆 coroScope{} 这样图文不符的结构。kt在UIUX界敢能和H5相比么?为什么语言多项功能,app的功能却少的可怜!

kt的结构化并发不比Go的WaitGroup(semaphore)有用,但新词一大堆,初心全忘了,开始比java还八股了。真可笑,屠龙者终成恶龙
那些比Promise更繁琐的,是毫无语意的知识,迟早被py AI自动完成。看来科学界也不喜欢代码圈整这些无聊的class

就问 https://python-future.org/ 2to3这么聪明又简洁的lib,java人们啥时候能学会?态度问题,不是智商低 #statement

协程线程进程,都是Job
jobs的管理上,除了^Z SIGHUP再 fg bg 恢复,内核还支持swap(整个系统的)内存页到SSD,甚至用CRIU直接把进程快照为文件。 这样的快照不仅能多拍,还可通过网络传输,简直易如截屏,又像 Termux.dev / Waydro.id / webvm.io 那样神奇;然而这样超越运行期的“时间魔法”,90%的编译器根本做不到,只能用reflect或asm模板这样的残次品搪塞;同理90%的语言里“函数值”都没有相等性--所谓闭包“值捕获”却并不能自动内联JSON,所谓RPC,protobuf还不如微软的COM,pwsh.NET普适
#os 在这一点上可比 #plt 的孤岛、围城,先进太多了
https://t.me/dsuse/19341

https://kotlinlang.org/docs/coroutines-overview.html
https://github.com/youngyangyang04/TechCPP/blob/master/problems/为什么用户态和内核态的相互切换过程开销比较大.md
http://cht.sh/podman

podman run -dt -name cnt busybox /bin/sh -c 'i=0; while true; do echo $i; i=$((i + 1)); sleep 1; done'
podman container checkpoint cnt
podman container restore cnt

https://t.bilibili.com/948850441406382096
#think #web #tool
https://cssgridgenerator.io/
https://crocotile3d.com/
https://fixupx.com/Oroshibu/status/1808500235263418441?t=BtGGBHj9jnN2AReHW2VTWA&s=19
三視圖?

有趣的建模工具
帅啊!
螺莉莉的黑板报:
(๑•‌ㅂ•‌)و✧
https://dataset.wav.pub/

https://brython.info/demo.html
https://github.com/Distributive-Network/PythonMonkey
#py
螺莉莉的黑板报:
https://github.com/baskerville/plato/blob/master/README.md

你们 rust 真是啥都能干……

https://www.sea-ql.org/SeaORM/

这东西好用么……求教……

https://gitlab.com/coolreader-ng/crengine-ng

有趣的引擎

https://chinese-font.netlify.app/ font
https://typst.app/universe/package/bob-draw
#svg

https://ivanceras.github.io/svgbob-editor/

#code
duangsuse:
大量复制粘贴十分抽象
list有那么难用吗
难道你没注意到近十行只变了1个参数
AIGC也没脚本化得这么严重吧

我看还是用list first!null好了,这么八股文…… 大家现在都是用get null取代预判has的

这种到处预判的风格,很像你找大佬问问题,先发「您在不在」,他只好回个在,然后你不在线……

表达式化比你想的要多哦:

>Spring如何把 @Autowired T xx; 换为 var xx=find(T.class)

var Ts = [T.class].map( applicationContext::getBean);

你在class{}里加那一堆定义,如果只引用了一次,就完全不应该引用。 到底都是要查bean的

从code smell来看,只使用了1次的变量名是无效的;如果只是为了易读新建变量,只能证明你的helper fn命名的有问题

kt已经有!! 了,还想要更多
Java 一大特色,注解属于元数据,和函数调用有重大区别

duangsuse:
那这是定义“随用随扔”变量名的理由吗
函数和变量是这么用的?
java以省略[""] 为由引入太多常量复杂度的优化了,都要所谓框架来解决

纯粹是make compiler happy,把一个schema弄成它能读懂的class,然后再强转Any来构造class而已

js里一个字典让java用就是这么麻烦,其实能用几次呢? init完就扔了,根本不是性能瓶颈。

注解的本意,应该和py的 @decorator 一样,是接受class元数据的编译期函数才对

而不是等到运行时才去查什么field有哪些@属性 然后逐个.set()

要动态生成一个类型,来获取注入,简直无理取闹。 明明就该在编译期产生Registry.get&fillNew的样板函数

这是属于既把元编程的路封死了,还不让基于注解的注入框架提供统一的“反射”方法

其实jawa懂这个道理,但它偏偏就做得很烂,就会个@Override
duangsuse:
为了编译速度这也太幽默了,其实,jvm作为栈机 基本就是带类型签名的GNU dc计算器,不需要什么编译优化

如果递归下降一遍,校验下类型 生成个push call 就能花什么编译时间,属于是用PHP的方式搞算法了

而且javac的能力还远没有到c预处理器的程度,为了优化? 我看是他们不在乎程序/类定义的优雅性

什么序列化啊,也没有做规范,和py能 import json,yaml,toml,marshal 能比?就一个用来RPC的ObjStream,还被业界遗忘,哈哈

汤姆猫是大专必学

虽然汤姆猫的Biz程度也就比Node http-server强半点吧

所以问题就是Result类型为何没有重载 !!, 让它看起来仿佛只是带有错误消息是null

凭什么!! 只能校验 Type? 呢?
assert也是乐观/悲观路径
Exception也是,为什么不能一起判定了?
还非得搞个ifEmpty, ifBlank.. ifNullOrBlank..
莫名其妙

duangsuse:
这不是废话吗?例如买30天大会员,肯定是30* 24*60*60秒后失效,这才是世俗意义上的电脑时间

看到py关于时间和日期/时差有3个API
我就觉得抽象

audit就是一个不懂AOP的,其实unix可以靠strace审查syscall,win32的 sysinternals.com 也有进程日志功能

与其自己搞个无人知晓的轮子,不如封装别人的,两全其美
把OS的活都包揽了,难道py是要运行在Ring0把内核驱动都带上? 那必须支持啊

绷不住了,抽象程度直逼jawa

一开始就不该搞所谓orNull
默认 first{}!! 就够了

我在js里都是把Error视为object返回值的特例,和null是一个意思
这样就不存在什么orNull orElse的,catch表达式也免了

就是语言设计者对值体系的理解不过关,例如NaN就是numbers的null才对,而不是什么number?
这样才能用统一的方法去报错/换默认值

可悲的是一开始就没把悲伤/快乐路径当问题啊,真是异常搞心态

duangsuse:
幽默IDE
完全相信它的API有一大堆根本用不上的class
忸怩作态的软件没必要去维护

kcp是这样的,可 import ast 自 https://python-future.org 就没变过😋
py只是用:隔离一个表达式先于=执行,就实现了高贵语言们的静态检查

既可以用于静态分析,也能在运行时查看f.annotation ,完备的数据不需要反射

btw. 大佬应该会做一个DSL
Message.invoke{ id==mid }
Message.select{ id==mid }//多项

可是这种写法才是真正的SQL逻辑式

既然Msg(id=)能构造数据, Msg{id==} 就能查询
这不是很合理么 #kt

很简单,如果做得太标准,以至于移植到任何一门语言里都没必要修改的话
就没人给官方docs贡献流量了

duangsuse:
https://www.liuwj.me/posts/ktorm-introduction/
🤔 一个SQL函数.xml codegen 能被吹爆,还有人卖课是我没想到的
ES6里一句 sql${} 解决的东西,哈哈

「没想到他文化程度那么低」……

怎么会呢,语句能缓存,再怎么也比一次加载完dao好

你要是不喜欢,或者不相信语法糖有缓存,可以做成生成函数的形式
例如
updateId=f=sqlFn2{a,b-> Pair{B/b, A/a}}
f("bye",0)

所以说,如果你不相信DSL能被缓存,可以转为生成sql函数的形式啊

这不是MyBatis++ ?

https://github.com/JetBrains/Exposed/blob/main/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt#L184

我只能说,缓存键要么是调用点或次数
要么是函数
似乎很难单独缓存DSL对象,除非对它们的构造器
幸运的是, key eq x 里x的修改能缓存,因为它是参数

https://jetbrains.github.io/Exposed/frequently-asked-questions.html#q-how-to-get-a-plain-sql-query-which-will-be-executed

https://stackoverflow.com/questions/74821893/postgresql-arrays-instead-of-extra-table-in-a-many-to-many-relationship
涨姿势了,以后 1:N用数组json N:N用join

duangsuse: #fp
要是kt能允许编译期生成一部分表达式,就没这问题了😅😅😅

可惜啊, unquote{bash(q(trim("trimedStr")))} 这当然是lisp的专利
其中q() 被生成为一个字面量,就像闭包捕获:
fun bash(s)=trim(s).let:
paste {system(it)}

并没有所谓的编译期,因为编译器能访问所有lib API


0开销不是瓶颈问题,但事关语言的脸面

明明就很有用,可被一些人理解为「并非瓶颈的东西」
然后被rustc拿来完魔法

要我说他们就是傻屌,只不过是把闭包「捕获」的实现方式,改为内联字面量(unquote)
就能轻松突破编译、运行的动静边界,根本没有引入任何新API ,没有什么循环展开和 kotlinpoet javapoet的区别

他们做成什么样了? 正则的缓存还不如py的拿dict查😅
duangsuse: #kt #book 元编程
http://www.bilibili.com/video/BV1XH4y1w7mT
https://drive.bennyhuo.com/zh-CN/talks/2018.11.17-%E4%BC%98%E9%9B%85%E5%9C%B0%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B_final.pdf

https://weread.qq.com/web/reader/f7632a00813ab82d6g017b14ke4d32d5015e4da3b7fbb1fa
可以一起读
虽然我不觉得这点值65😊

如果numpy那种API/DSL都设计不出来
修改class的结构也只是给开发者们徒增烦恼罢了

举个例子,此章节的 gh/user/_name
如果只是把它当成URL路径,需要绑定,显然造成代码重复,与元编程的本意违背

而如果像 import fire 那样,知道URL的本质是class路径与def GET,POST等,也就是另一种CLI调用
就不需要写什么注解和函数名
甚至模块化都省了,一个文件足矣

不过是修理servlet.xml繁琐和不支持argbind和的“弱类型”问题
但何必要制造那么多问题呢?sql,http,那么简单的工具还用学

#parser #learn
说起来,AST也就是多方法的 ()->Any 而已
你甚至可以把方法名enum化,从而完全避免使用class
例如 sum(L(1), L(2)) ()==3 只需要两个fun
Object Algebra.. 嘛,用虚表override取代if,稍微快点,只是要parse两次

至于在js里,我一般用 [[JSON ',' +] '()' /] 这样的模式写ast
描述 (1, 2, 3) 这种正则
甚至连函数式都没用到。 数据结构本身就蕴含了for if流控,运算符重载本身就是编程语言

不需要任何范式来实现他们,“数据结构与程序语意直观对应”,这就是CS。
这……应该是一件很难听懂的东西吗? 为什么DSL都设计得那么刻意和拉垮?

甚至,构造函数也应该取代class{} 或tuple才对,为什么把参数传递到堆而不是栈里,就需要写所谓的struct? 它们都是把args打包复用而已
为什么把yield 外提为语句,变成
let then=回调=()=>switch{} 里的编号,就需要学什么func*和async,堆和栈,难道不是天生一体的么? 分页数组、“缓冲区”,难道不应该是跨语言的?

然而支持kwarg的python 却需要Namespace来实现这种等量代换😒 反而是Haskell可以这么写
然而它是真正的笨蛋美女😅

#oop
元编程,首先就要明白obj的本质是通过enum分派逻辑的(vararg Any)->Any ,也就是一个when(x)in constMap+super..
这样才方便添加和绑定方法签名

这样在语法上也就能理解为什么是{}包裹,以及filter{}为什么优于lambda和匿名override

py可以通过vars(o)实现静转动态
typing.Namespace(kw)反向
除了小写类型不能扩充,哪怕是Ruby元编程在直观上也无法和它相比了

duangsuse:
oop和rust go就是pp的扩充
不算重新学习过过程试

编程语言只不过就一张加减乘除节点图,问题是领域和API

看这本书的“层次结构”,就想到拿identifier叫name,拿classifier叫tag,拿些辞藻和皮毛当本质,哎
无聊
好像早点拿到电脑,多写代码
#kt #code 😊之前,v8 blog说Promise就是Continuation(含续体的回调),我还觉得多此一举
和Kotlin“强大”的API一比,我却要变成ES6吹了。Web的先驱者们简直是先知啊! 代码越复杂,成品功能越简陋。这就是为什么安卓app体积不断膨胀,功能却越来越卡。

interface Promise_<R,T> {
fun then(ret:OrErr<R>) //delay() 后应该这么做,那之前只需调用它并return。它通过cpu{}排队,另一种排法是yield Promise
//launch(ctx=Main+CoroName("val")) Map状链表DSL。Job等元素
var cpu:(Runnable)->Unit; name=""
fun go(:T?):R
fun stop(:ErrStop)
stdState=0,1完成,2取消
//不要使用截获器和Key环境变量。组合优于继承,go 的WaitGroup比不伦鸡肋的scope明确多了,Android的curl比js的fetch流更复杂吗?
}
type OrErr<R>=Or<R,Err>, Err=Exception
val OrErr<R>.!!: R
sealed Or<out A,B> {
data A(:A) data B(:B)
fun as(A->R?, B->R?={null}): R?
val A:A? val B:B?
}
fun T?.as(R, T->R):R
fun T?.as(T->R):R?


😊顺带把阿K没有统一的err/null错处也搞了,还要什么 o?.x?.y ?: 1
https://www.bennyhuo.com/book/kotlin-coroutines/12-why-so-called-lightweight-thread.html

上面说协程=Thread.asCallback() 只是一种go/lua的罕见情况,好理解嘛。
kt里协程是通过retAddr()作为参数,实现的链表化调用栈,其第0项一般是 runBlocking{}或thisCPU.nextJob
这样可以在主循环注册任意个delay()或flow{}的回调,优化 Promise.all。这是虚拟线程所不擅长的
https://www.bennyhuo.com/book/kotlin-coroutines/13-implementations.html
duangsuse::Echo
duangsuse: #kt #book 元编程 http://www.bilibili.com/video/BV1XH4y1w7mT https://drive.bennyhuo.com/zh-CN/talks/2018.11.17-%E4%BC%98%E9%9B%85%E5%9C%B0%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B_final.pdf https://weread.qq.com/web/reader/f7632a00…
duangsuse:
此callback非彼回调
这个cb是编译器自动生成的class

web apis从一开始就线程无关
有什么平台和语言敢说自己的异步API比Promise经受更多用户考验?

那个是动态语言所必须的,kt有编译期,完全可以不染色
然而只有suspend fun是和正常函数完全相同的,业务上完全没有比js优秀
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
algebra effect https://t.me/dsuse/19174

coroutine这个词不需要存在,即便是在脚本里,最多需要await和numpy的真正并发并行计算

而且即便存在,霍老也不应该说什么magic
不过就是把return()变成值,通过callLater{delay.then(me)}构成链表,要么就简单到 Thread.asCallback

可以知道,Coroutine(而非Closure), Dispatcher/awaiter 都只是为确保函数return后能正常复活的东西,和调用栈完全一致
强调它们不同的,不是蠢就是坏

堆栈互转的玩意,说的跟迷因似的术语一大堆,严重被高估了。OOP构造函数同理
还有元编程、xml ,完全是语法太复杂导致的无效学习。你看 compose DSL需不需要拖拽设计器

coroutine是在搞特殊,因为linux的read() write()就是自己的await和yield,linux没有说协程
多线程是为了IO多路(evpull)和分块计算之类的,linux没法掩藏这些细节,但语言不掩藏就是语言愚蠢了

反倒是lua以后那么多年没有语言跟进,都在回调地狱,这是问题。

lisper 在把 @Adder(x=2) 生成为 (unquote '(+ 1 x)) 时可不会觉得是魔法
他们写 (let '([x y] ary)) 时也很清楚,这不过是一种list(str) 的循环处理
kt写inline也不会觉得很难理解

也罢,毕竟字符串模板目前还是ES6的专利,php都还在sql注入呢
所以java语法比嵌套的括号还低端吗

我是说无缝RPC其他语言脚本的这回事
sql``select ${1} 是不会注入,那为啥sql里有个 ?参数的概念呢?

PHP通过ORM和prepare语句确实不会注入,那么php跨语言调用js脚本呢?
只能用reflect.invoke那种API吧?

ES6可以随便调用任何py js rb JSON接口而无惧注入

不仅如此,js还可以靠eval('var ..') 自己注入自己,顺带实现codegen

想不想注入,都是开发者说了算😊🤓

#statement 我一开始就说了啊,讨厌magic

作者在后面的章节明明有更大体的理解,却不懂知识重构
反而把这些含语言设计者私心的API拿来讲课

两句话说明白的东西,何必浪费读者时间。后面讲Channel,sequence,flow 时读者懵是不是还要复习一遍?

最讨厌与语言、与CS术语耦合的私货了。 谈算法不离编程语言的,两句话不离语意模糊的术语的,可能是称职的程序员,但绝对没有准备好设计优秀的框架

这让我怀念 coolshell.cn 的耗子,虽然他过劳死了,但不到50不写书的工匠精神确实值得钦佩,因为知识布道者确实要这样谨慎。
要是编译原理/元编程界的多数人都这么有格局,lua zig的这些优点也不会雪藏那么多年, http连双端绑定都做不到的框架也不会活那么久

duangsuse:
#kt coroutine 和现在js async func* 的情况一样,一开始没有flow,后来加进去就是。。一言难尽

我不觉得把分页数组和Reactive混为一谈是好的
就像现在flow也需要buffered()或只留最后一项
这不太能统一化缓冲区

🌚flow模仿数组好像也说得过去,但总觉得有点像C数组或指针,是在搞混淆

flow如果和sequence{}统一就更好了,使用可调的默认bufsize而不是yield一次一个值。

这样和linux的iostream就合体了,而且也能实现vue ref()的效果,两个不耽误
太过重视调度线程是在模糊要点
#kt #歪点子 inline class 来了,const fun 就端上来罢🤓🤏 https://youtrack.jetbrains.com/issue/KT-14652
https://kotlinlang.org/docs/inline-classes.html


const val x = encrypt("password")
const val hash = md5(File("config.file")

val routes = arrayOf(
get("/hello", (req, res) -> "Hello World");
get("/fizz", (req, res) -> "bazz");
);
dispatch(routes); //2* if

const val MEMORY_SIZE = 640.kb //fails now
const fun p(num: Int) = it == 0
typealias Zero = Int / ::p
//现在的带验证类型
value class Even(val num: Int) {
companion object {
operator fun contains(num: Int) = num % 2 == 0
}
}
& being able to use the return value of a constexpr function as an annotation


replies Andrey Breslav:
The main use-case is 'documentation'. See the resent example of discussion for "nameof" here: https://discuss.kotlinlang.org/t/nameof-to-get-names-of-program-elements/1518/4

https://github.dev/rust-lang/rust/tree/master/library/std

there are apparently 990 functions in their stdlib that have been converted as const fns

https://tech.youzan.com/java-metaprograming/ #learn 元编程是什么?为什么js人搞JSON不需要靠元编程?

编程,就是用SDK给的套路解决问题。
元编程,就是突破病态类型(仅编译期可见的静态类型) 的桎梏,编写能写代码的代码,即codegen函数,从而实现编译器没有自带的功能,例如打印“class指针”里的内容

☺️我有一个绝妙的点子替掉 https://square.github.io/kotlinpoet/ ,只是手里的屏幕有点小,写不下
https://github1s.com/bennyhuo/Kotlin-Trim-Indent/blob/master/trimindent-compiler/src/main/java/com/bennyhuo/kotlin/trimindent/compiler/TrimIndentIrGenerator.kt#L34-L81

瞄了一眼,发现截获覆盖字面量调用是挺简单的
Forwarded from duangsuse
哎,没有心情看 #kt #book
看了下codegen技法,只能说近十例子里anko的风格相对优越,和html一样是用twig(类似erb)模板,然后作者函数复用还行,但也没有到90分的程度。

例如“贯穿全文”的DeepCopy(x:T)吧
js里相当于x就是T的反射,又一切皆可变,可以直接读写{...x}[ID], 只需
mapEachMember{if(it.isPrim) it else DeepCopy(it)}

kt里需要用构造器复制,先拿到 T.vars[ID].get(x)而非 x[ID],但依旧是 mapEachArg{getattr(x,it).primOrCopy} 的模式,这个至少适用于 Tuple$N的toMut和url参数绑定
这就是个小学算法,反射和List API 的良莠不齐却让它很难看。

重要的是独宠XXpoet 真的无力吐槽,和那个 https://t.me/dsuse/17514 一样,就一个不用导包,然后自带formatter。简直可以说是一碟醋级别的算法,甚至应该叫搞错重点

和我的tkgui https://t.me/dsuse/19768(py基于getattr等元编程,运行期生成等效调用赋值图代码)
都没法比,何况最近我在设计表达式级(fun{}内计算图)都能建模的跨语言、带裸类型推理、动静合一OOP元编程范式了,这种拙劣的"xml模板"实在写不起来

java确实是“病态类型”,而非什么静态检查。 连数据树的验证和walkDeep都要靠魔法,有什么资格谈类型签名的那些好处?
靠被默认值参数替掉的重载吗?

只能说,如果手头有电脑,我应该去吧那个sql dsl写了😒 而不是在这看java人像手写sql或xml那样拼接字符串
不知道 unquote(ast) 这种函数式代码生成,起码吧 quote(litOrID)做一下,免得被注入弄出无效代码啊

再说说全书结构,首先就没有谈元编程是什么,而是java老三套:环境配置、难题、抄代码

好吧,可是一个优秀的老师应该选循序渐进,但却对知识体系至关重要的例题: #learn #plt

- 为什么是靠C的#define 自主研发出易语言?预处理比str.replace多了哪些? 高亮分词后,灵活解释“常量字面”吧
> eval("[1,$x]") 是一种JSON解析器,可是x="][0]"时似乎有bug。 修好它,然后把js爆改为你希望的“易”语言(复用猜数游戏的REPL)。 完成后类似的bug应该仍然存在!
其实,js源码也有它的JSON.parse,它就是反射的原型。
- 比较下SQL的'?'、C printf、ERB/ES6模板,kt元编程最缺少的语法为什么反而是"$str"? 控制变量,就能明白pwsh和ts为何比bash和js有长期编程时的优越性

- if os==nt6: class: 与#ifdef _WIN7 凭什么是同构的? 动态类型,依旧是Java式的类型。宏,并不需要魔法
- 为什么Java8让 invokedynamic负责创建lambda,getMethod不也能.invoke吗
- 局部fun 一定要 ::引用的背后,藏着一种元编程,T.(A)与(T,A)->、(T?)!!的强转背后也是! 原来除了消除重复,她还让语言提供更有价值的“值类型”
- 为什么“闭包是穷人的对象”? C语言里回调函数去哪了?SAM接口又为何比到处new.object{}流行? 原来返回函数、重写接口也能费内存啊

- 为什么pyjs里很少人研究元编程,但却又有 python-future.org 与vue,babel这样的全民应用。 二者有何区别
- Proxy(obj)掉包属性,是动态类型元编程的专利吗? reflect.Proxy 能生成函数,还不止于DSL或AOP!
- 能不能通过函数重命名,用py风格的反射API实现KAPT的 @decorator ?哪怕只是封装Reflect?这能让你学习跨平台移植,收获超越本次需求的心智模型和视野
- Kotlin对dynamic类型表达式链条的“零修改”生成规则可以怎么实现,numpy里也可以吗? 这能帮你理解DSL和编译优化的本质

- “优秀的程序与其读写数据的结构直观对应”。纯函数式编程(例如rust的enum和if let) 做对了什么? 为什么你仍然选择不够纯的Kotlin? 这种enum能表示JSON乃至HTML的序列化结构。
- bash风格的参数有3种,其中一种如 ls -ar(all reverse) 传入enum:BitSet。用fun demo()出完整函数签名
- 以上问题和codegen无关,也没有教你具体怎么生成url/json/sql绑定类或函数,却给你了设计相关框架的能力!这次由我来回答,为什么javapoet是对pyjs里闭包list/dict的拙劣模仿,以及反射调用为什么就是在codegen!

所以。。 虽然《Ruby元编程》教你的只是一些OOP特性的“工作原理”,而案例较少,但我更喜欢它 --它让读者真正建立起了对"class"这个dict的理解,加上dyn(*arg,**kw) 本就可以用名字动态查,让读者对“把def和class 视为一种constObj去查询、实现复制粘贴、...”有了把握

而不是一个看似什么搞法和IR,ASM都贴出来了
实际上对你没有用,只是让工作失去焦点的troublemaker🌚🌝
duangsuse::Echo
duangsuse: #kt #book 元编程 http://www.bilibili.com/video/BV1XH4y1w7mT https://drive.bennyhuo.com/zh-CN/talks/2018.11.17-%E4%BC%98%E9%9B%85%E5%9C%B0%E4%BD%BF%E7%94%A8%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B_final.pdf https://weread.qq.com/web/reader/f7632a00…
#kt #元编程 嗯。。我有个点子,有没有懂ktx序列化的人批判一下😊

基于Visitor实现json/toml.. 的读写,data class 只提供零参构造和 KVlit.see(instance,"field",jsonVisiter)接口

数据类的KVlit,就是给dict支持了个拆箱赋值,结合零构造和field Visitor自然而然就实现了序列化
设计CLI解析器时想出来的,就挺像xmlpull

const N=Double
data Num2(x:N,y:N)

interface KVlit {
fit(o:Any?, k:StrInt, v:LitSeer)
companion 注册表: IType<KVlit>
}
next=File(..).jsonLits

typeof<Num2>
(KVlit).fit object:LitSeer {
see(x:N):N =next.Float
//我们要read,所以忽略旧x
see(o:Any?, T:KVlit) = skip'{', T.fit(o, next.Str, this).. defaults(o);return o
see(o:Any?) //null模仿动态类型、Any.kvlit.testy 不为空

//BDFL optimize (Boxed ints, Date/Decimal/UUID, float[]s, List Map<,Any>
o.(Integer x)仍调用int返回的重载; int[]在长度不变时返回自身

see(o:MutKV<*,*>, K:Class,T:KVlit?) //传入Class.INT等常量即可
see(pair:Any?, T:Class, vararg Ts:KVlit?).. //可通过实现 typeof<Pair>(f2Any)转接list,base64
}

这是读取,写入的话接口一样是
x=fit(jsonStream,x) 。如果 T.seal? 字典不为空,就先读个'type'键 然后同上。 期间 T.setLit Bitset用于检测是否需赋默认值

扩展的话,直接 override Visitor 的最后一个函数! 数据、格式、模块,完全解耦

codegen上就是一个大when{}的语句字典
然后对diff update(亦可DeepCopy)
以及CSV(KVlit能实现.eachIndex)很友好,这点是我最满意的

想支持ClassFile等binfmt,除了重写list,sealed编码还要支持 UInt,bitstruct,Magic012,CPool<> 等类型,但比从头开始好

实现上, T.fit(o,key,this) 应外提为线程局部 T.fit(o,key,)KVlit.seer
T.fit(map,T,)KVlit.mapK
应支持创建iterList.setEach{}随访问更新流
duangsuse::Echo
>火之魔女: 不过unification我是想写好久了(应该按年计)但是一直没写的( https://github.com/duangsuse/mkey 写过,不过落后很久了 #sql 这算法就是 unify(a,b); unify(a,1); unify(1,a) 得出 a.v==1==b.v reify([a]) 解引用一下=[1] ,其实也挺有趣,包括npm也在牵强附会这玩意,真让人搞不懂从哪看的 http://minikanren.org/ 使用了一个自有的def: yield 实现,对 a&b…
#OOP #plt 学点设计模式
https://iota.huohuo.moe/OO-in-C.html#:~:text=一种设计模式对应一种语言特性%20%20By%20千里冰封

函数式人有许多「过度设计」,例如美 kotlin.Any.let 其名曰 #FP Functor.fmap (Arrow-KT.io)。这种(私货+算法)的泛滥,给IT带来了灾难,让许多初学者不明觉厉,也当然不能提升其应用能力(毕竟只是"指针别名"嘛)
https://kotlinlang.org/docs/scope-functions.html
https://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html

但OOP也有自己的“私货”——用于弥补语法不足的“优雅的”设计模式
例如 Builder,Utils,Adapter,Delegate.. 它们是对this参数、对interface扩展不够灵活的变通

这个长文,我会用短 #kt demo 让大家看到 refactoring.guru 🐿收录的10种流行 Design Pattern 掩盖了哪些语言特性的缺失
以及科普"OVDEP" Observer Visitor(深先iterator) decorator(单参compose) EitherAB Proxy 等不逊色于箭头函数的,超越语言的优秀工具

## 创建性-Creational

这些模式是 new 构造器() 的变体,在Rust里被 fn new=Pair{A:1, B:2} 构造字面和 impl T for T1{} //mixin T1: T 混入取代

1. StructBuilder

有一个很长的SQL row需要new,可以使用默认值,插入前也有检查

class RwCol2<A,B> {
var A:A?; var B:B?
constructor(x:A,y:B){A=x;B=y}
constructor(){A=null;B=null} //默认值
}


我们把构造器中A=x;B=y; 拆成 newThis.A(x).B(y) 两个函数,就能实现初始值的解偶
填完数据可能要验证,如编译期验证不可变 fun build()=this as Col2

与它对立的是默认参数
RwCol2(0,0).apply {B=B+1}.B; buildList{} this参数上扩展 apply(T.()->*): T
K2 value class{init{}} 也实现了构造后验证,不过大部分人仍在使用专门的反序列化和data verify框架

2. (Abstract)Factory

常见误区是,Factory类似 Pair.of(1,2) 是为了重命名掉new,或者只把构造器集结起来: doc.createElement("div")
安卓 content.Context 与Button等View(ctx)的关系更像工厂的本意: 基于(操作系统)上文验证和保留数据

interface DataJVM {
fun <A,B>List(a:A,b:B): Pair<A,B>
fun <T>List(vararg x:T): List<T>
}
val kt=object: DataJVM {
override fun <A,B>List(a:A,b:B)=Pair(a,b)
override fun <T>List(vararg x:T)=mutableListOf(*x)
}
//val py=object:DataJVM{}


与它对立的是全局对象、元类trait。
全局fun弥补constructor钉死了 open fun 且难于校验的问题。当然!它也消灭了 object Singleton{} 和“双检锁”的样板
元类允许了 static (类名上)接口,而不是让可覆盖的函数代理一下构造器:
https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineFactory.html

3. Prototype

Linux对pwd等环境变量的fork()是最著名的原型模式,这使得父子进程间有了T1继承T 的关系
JS里 {} 等价于 {__proto__: Object.prototype} 函数表,函数表也可以随时添加继承。有 new.target 的构造函数()只是设置原型+赋值到this的简写
一切皆对象,除了 Object(1).valueOf() 里装了又拆箱的1。无原型的,只有更慢的 Obj.create(null)

data class 会自动实现 fun copy(),但它不能继承,因为无法拷贝父类的变量。Java里很难把对象加构成更大的子类(除了 inner class)
sealed class Box<T>(val A:T) {
inner class Pair(val B:T): Box<T>(A)
}
val x=Box(1).Pair(2)


按道理是x.A=1,那么Box(1)单例就是这些Pair的原型