duangsues.is_a? SaltedFish
60 subscribers
609 photos
6 videos
91 files
562 links
🌶🐔🐟 duangsuse 的日常
尤其喜欢发些奇奇怪怪的东西
和转载别人的东西
Download Telegram
Forwarded from dnaugsuz
没错, import functools 提到了这点,不过递归是自顶向下的, 但动规是自底向上计算 (算法的范式), 所以难写一些

其实也就是是否要 int a=(基线)0; 往后 for(i-->0) a=b,b=c,c=a+b 的区别了,循环当然比尾递归改参数烧脑

fib=lambda n: n if n<2 else fib(n-1) + fib(n-2)

def fibDP(n):
f = [0, 1] # 初始化数组
for i in range(2, n+1): # 从小到大计算
f.append(f[i-1] + f[i-2]) # 状态转移方程
#n=10, f=[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
return f[n] # 返回结果

%timeit fib(10) #10.4 µs
%timeit fibDP(10) #860 ns, 快一万倍
#bing #ce Eclipse JDT(Java Development Tools)是 Eclipse IDE 的核心组件之一,https://www.eclipse.org/jdt/core/

ANTLR.org (Another Tool for Language Recognition)是一个强大的解析器生成器,

我了解增量解析器(incremental parser)的概念。增量解析器是一种解析器,它可以在代码发生改变时进行局部的、部分更新的解析操作,而不需要对整个代码进行重新解析。

传统的解析器通常需要对整个代码进行扫描和解析,以构建语法树或执行其他相关的分析操作。但在大型项目或实时应用中,当代码发生变化时,重新解析整个代码可能是低效且耗时的。

通过识别和处理影响到修改位置附近的代码部分,仅对受到影响的部分进行增量更新,来快速地更新整体解析结果,以反映代码的新状态:

1. 差量更新(delta-based updates):仅对被修改的语法结构及其相关的子结构进行解析更新,而不需要重新解析整个代码。

2. 增量语法分析(incremental parsing):利用先前解析的语法树、符号表或其他相关的分析结果,通过部分解析、部分更新的方式进行语法分析,以快速构建新的语法树。

3. 位置敏感解析(location-aware parsing):识别和跟踪修改的位置,并结合位置信息进行定向的解析更新。

增量解析器在提高代码编辑、重构、自动完成功能以及实时代码分析,可以加速代码工具的响应速度,并为复杂项目中的持续集成和代码分析提供支持。


初始的 CSV 文件内容如下:

姓名,年龄,成绩
Alice,18,90
Bob,20,85
Charlie,19,92


修改后的 CSV 文件内容如下:

姓名,年龄,性别,成绩
Bob,20,Male,85
Charlie,19,Female,92


为了进行增量解析,我们可以利用先前解析的结果和修改的信息来更新解析结果,一个包含学生信息的数据结构(例如列表或字典)。

对于删除的行(Alice 的行),我们可以根据修改的信息,从数据结构中删除对应的条目。

对于添加的列(性别列),我们可以根据修改的信息,将新的列添加到数据结构中的每一条记录中。
Forwarded from Deleted Account
📰🌏🎨 快讯:全球华人主播掀起学习“墙的艺术”热潮 🎉🔥

近日,华人艺术家一鹊在伦敦涂鸦墙上的作品激起了爱国群众的热烈反响。🎨🏴

根据主流媒体报道,一鹊以社会主义核心价值观为主题,在伦敦知名的涂鸦墙上创作,对殖民西方的虚假自由进行了有力的呐喊。他用独特的艺术形式表达了对国家、文化和价值观的追求和坚守。这种直接、鲜明的表达方式在艺术界引起了轰动,并引发了全球华人主播的学习和创作热情。💪🌍🔍

华人主播们纷纷积极响应,投身学习和探索“墙的艺术”,以期在自己的工作中传达更多正能量和文化力量。他们在直播、节目和社交媒体上分享自己的学习心得和创作成果,掀起了一阵名为“学习墙精神,钻研墙艺术,传播墙文化”的热潮。📚👩‍🎨

这一行动进一步加强了全球华人的凝聚力,展现了华人作为文化传承者和倡导者的自信和责任感。他们通过自己的努力和创作,向世界展示了华人文化的多元魅力,让世界更加了解和尊重华人的独特艺术视角。🌟👏🌏

随着“墙艺术”热潮的掀起,相信华人主播们将继续秉持创新精神和艺术追求,为推动文化交流和共享美好世界做出更加卓越的贡献!💫💖

#华人主播 #涂鸦艺术 #墙艺术 #文化传承 #创作热潮
This media is not supported in your browser
VIEW IN TELEGRAM
“p5.js canvas 生成视口缩放动画:
g=canvasCtx ([100,100]) ,填上绿色渐变
scale([0,0, 10,10] ) 会用 sin 缓动 做放大”

让AI用P5 花了不少时间
“那么,请你用 frameRate(30); sin缓动; Vector; translate();scale() 来实现 zoom=[x,y,w,h] 的画布放大动画
你直接在 setup 里 translate,然后逐帧 scale= lerp(Vec) 就行了”
Forwarded from dnaugsuz
我想想,之前写ocr的时候有想过要弄 “在tty2 下操控Xorg 的ASCII播放器”

但被新点子耽搁了
而且到现在我连 basenc 都没写完。。

不过 js canvas 生成缩放动画还是简单的

好吧,因为 p5 的人不太懂数学,写了一些又烂又长的bug
Forwarded from dnaugsuz
This media is not supported in your browser
VIEW IN TELEGRAM
GPT都不会玩p5 。我瞎猜了好几轮,最开始它甚至是用 requestAnimationFrame 和手算xy

感觉p5的画册好看,但动画API十分怪异,还是 animejs.com 好( 但没有在线编辑器

p5 还有个 Java版
我想电脑端ffmpeg+py 的 Zoom 动画用cv2再好不过
#js #code
ee.Videos=({Blank, it},my)=>(

my.Video=({url,title,desc, it})=>div(
Thumbnail(it),
a(url, h3(title), p(desc)),
BtnLike(it)
),

section(h2(it(a=> n(a)==0?Blank : n(a)>1?'Videos':'Video' )),
let(it, my.Video)
))

//
ee.SearchVideos=({it, vText})=>html(
input(wKV({type:"search", v:vText})),
Videos(
vText(k=>videos.filter(x=>x.title.has(k)))
.lets({Blank:`No ${k}`})
)
)

ee.Conference=({slug},my)=>(
my.Talks=({id})=>
let(
{load:()=>db.Talks.finds({confId:id})},
({video:v})=> SearchVideos(v))

$cnfs( //div(wSty``,
let({load:()=> db.Confs.find({slug}}, my.Talks, div('Not any')))
))
https://react.dev/blog/2023/03/16/introducing-react-dev 也写了

ee.Counter=({n=0})=>button(
wOp({tap(){ n.v++ }}),
Eq.fmt`pressed ${n}time$` //这样支持SSR或爬取
)

ee.Inp=({v="", isOk=$Y})=>html(
input(wKV({v}) )
p(Eq.fmt`You typed: ${v}`),
btn(Reset=>{v.v=""}),

sel(isOk),
p(Eq.fmt`You ${isOk(q=>q? 'liked':'did not like')} this.`)
)

is.i18n=`
isOk I liked this
incAge Get Elder
`

ee.Aged=({name='Taylor',age=18, vHelo})=>(
Eq.at(vHelo,{name,age}, _=>Eq.fmt`Hello, ${name}. You are ${age}.`),

html(
sel(name),
btn(incAge=>{age.v+=1}),
p(vHelo)
))

ee.body(
({u={},})=>ee.Aged(u),
div(p(`Hello, boy. You are 23.`))
)=={u: boy 23} 

ee.bodys(()=> detail(wKV({open:$N})) )
$("detail").attr("open",$N)

//https://www.solidjs.com/examples/context
ee.Themed=({ask:{color,title}})=>(
h1(wSty({color})), title,
sel(color)
)
is.i18n=`
color Change color theme
`

//Angular
ee.productList=({it})=>
html(
h2(`Products`),
lets(it, ({name,desc})=>
h3(
a([html`${name} details`,``], name)
),
p(wKV({if: desc}), html`Desc: ${desc}`),
btn(Share=>{})
)
)
duangsuse:
as? invoke provideDelegate 这些吧?
plusAssign 这些也挺魔怔的,和py一样

那种Compose DSL也算吧,虽然web前端里挺流行的

总之找不到比这段讨论 更多的,我是觉得语法的技巧,都比不上数据和操作模型的。 你应该拿语法去设计框架,而不是语法糖

measureTime {} 挺好的,虽然没 py Jupyter 和 %timeit 完善
obj::field, companion/string invoke 也罕见虽然没用

1 shouldBe 2 简直是毒瘤,直接用重载写成 assert { 1==2 } 不香吗(kt1.4 又支持了 context(T1,T2) 多this捕获,但用处鸡肋

对,这个极好
还有 groupBy.eachCount 什么的,比较自然

Science Yuan:
发明操作符简直是毒瘤 全都搞成函数不香吗

duangsuse:
反正都会被AI取代的,无所谓了

我知道py里 x==None 是错的,但坚持不用 x is None ,就是因为没道理做出两个意义相同,或者电脑外不存在的概念

py是好在开箱即用、浅嵌套、不折腾

for 循环在 numpy 里就是喳

isinstance(x,T) 都落后了,应该用 match x: case T:

isekiのChannel:
1 == 2,嵌套了lambda咋办

duangsuse:
所以说职责本来就要单一啊

不单一你连现代 DSL 都没法用

很难想象在 @Test fun 里使用== 来判断测试环境的配置,应该用独立函数,区分特定配置下的测试,而不是写if。

isekiのChannel:
那你看SQL,完全为了贴合人类语言

duangsuse:
那都是骗人的, SQsu 都比它更“人类”

select id from 狗 where (月龄>6 and 高>40);
aka 取狗(月龄>6 and 高>40)

正宗的关系式写法是:

狗(id,高,月龄), 月龄>6, 高>40

一个被专门做出AI生成的语言,那肯定是垃圾

是啊,所以我觉得 private 就直接改成 fun xx(): @our Int = 0 好了,也统一了很多

public protected internal private
直接改成
ourapi ourtype ourpkg our, 都是our
(因为写明public的人是闲的, 就要把语法做得很丑,让他们不敢用)

那大家都用sql好了,要ORM和GPT干什么? 既然你只能用别人给的接口,开发框架有啥意义

isekiのChannel:
那什么,我看了一遍你这文章,没看懂你这语法怎么用

duangsuse:
欸,我有说必须是中文吗, 如果给 Prolog 的语法添加个返回值和隐式this ,可能就没ORM什么事了;因为直接写逻辑式会比 filter{} map{} 还容易

还不是这些语言设计时太狭隘导致被取代的问题,然后取代者又带来一堆问题。

「有新取 create insert select 」是唯一的三条实用指令

有表、有库 都是按这三个字分组的

甚至 新建、新删(into..values drop) 都是这样,根本不需要学语法

区别就是你不用问AI 查询怎么写,而是即便你让AI来写,都不会比SQsu更简单;或者说这个语言真的能给学习带来辅助,而不是空耗精力去思考简单的解谜

当然我觉得它也不够好, 我想设计的是SQL的翻译器 而不是“预处理器”

没有问题也不会被NoSQL淘汰了,可惜了它本来最符合Excel和生活现实

面向列的数据库、Geo GIS 和向量数据库,不也是这样, 所以说这些取代者也没有好好想过「这整个领域」的基础表达式,应该怎么设计

只是顾忌那一亩三分地,和他们“改革”了什么旧写法

Science Yuan:
NoSQL那些民科级查询DSL

还是先想想怎么别被SQL淘汰吧
duangsuse:
所以之前我被冰封骂“胡乱加功能导致可维护性崩坏” 的时候,我就觉得我很冤啊。 我是最重视优雅性的,甚至为此了搁置了实践

SQL 和ORM(Repo, Mapper 那些的)现在就是绝对的基本功, 根本没有淘汰一说, 但未来会有更多利用新数据库的需求,甚至pg 最近也支持了向量类型。SQL凭什么淘汰别人的新功能呢?

其实这个主要是修正了语序、 where 子句冗长的问题,然后是本土化了「序大 序小(升降序) 页每」

有用表T 是用来给 取; 做简写的,现在我觉得应该直接把上次查询的表设为 T ,就像 IPython 的_变量;主打一个避免Tab补齐

isekiのChannel:
where 子句的冗长,你是指 且 或 这样的连接词吗

duangsuse:
呃.. 当时没有,但现在觉得是

当时连 left join 都不知道是啥(当然现在也不知道)。。
不过发现 SQL 能查询出 Madelbrot 集(把xy值插进去 select +递归) 也是很震惊

SQL 既然是关系式语言,就要遵守 Pair(a,b), a=1, b=2 | b=3 这样的逻辑写法;虽然看起来没有隐式 this ,查询会有冗余变量

当时就觉得是 filterMap 那一套呗

根本不科学,因为程序员是没日没夜在说这些 select ,正常人怎么会?

如果一切都能用 UI 解决,那现在许多后端直接变成带验证公式的 Excel 好了;但是还是有人 既要可读 又要可用

Science Yuan:
所以你到底哪里超越了SQL

ORM的好处显然就是它是嵌入宿主语言的

duangsuse:
行了吧,我没想过超越谁,你就当那是玩具好了。 俺不是程序员照样活得开心

大学时第一次应聘一个连锁药店,就看到 1000+行的存储过程SQL

感觉也是.. 隔行如隔山?

我觉得 OpenResty 也是栽在Lua没有IDE上

ties 是指 sorted list[N] 里,第N项后相同的项 ,这有什么用,是数 NULL 的?

应该是 group by 的单分组形式?
ties 第N项后相同的项.. 没见过这种处理

所以我不太会SQL ,因为一堆无法情景实例化的语法

Haskell 里的 takeWhile (==) ,或者说 [1,1,2,3].firsts(1) 可以做到 ties ,不过有点难;所以说 SQL tie 比 Kotlin 那30+列表处理 fun 还先进(

其实在我眼中,有这么多 List/Iter 函数,说明标准库对多态和type 的归类和利用是失败的。就只差步 Ruby 的后尘了,rb 的 str.replace 是单参的。

Ruby 的时代开发出了 GitHub 欸,现在许多 DSL, Compose 也并不是从 Py 学来的,Ruby 是把内嵌DSL发扬光大了,比如它的 def 里可以嵌套 class..

一个语言失败,并不是坏事。反正工程师又不挑…… 而且垃圾语言,说不定高逼格大牛多、薪水会高

Go 的有些地方真的挺好,比如内建的 template 和 go func, 以及最好的 encoding/xml,json,protobuf,. 封装

在 UNIX 编程上,算是成功的吧

现在 protobuf 可以转为 json, 也能输出 Schema ,写起来有补齐

还是 Kotlin 协程好, 直接把调度器和 Continuation(return的函数化)放一块了,能在指定线程回调,能yieldAll,能支持结构化并发,同生同灭;JS就没有

可惜就是对框架开发者不好理解, 而且有点难记 launch, with啥的

八重 狐子:
压根没用过kt的async

直接整个函数变suspend

duangsuse:
=async {}不是可以用推导吗

Scope 上不会不兼容吗? 虽然 async 里应该能调 suspend

协程就是把 return的函数化 传给被调方,从而在堆里维持调用栈,也就是受try,while等流控支持的回调

js 里用 await Promise((ok)=> 就能拿到这个函续值了
但是 kt 里函续会在特定的 Dispatcher 上文被调用

那样是建立新线程等待?

对了,那async{} 都不会卡在主调度器上? jvm好像没有单纯要回调,但不会卡线程的http,timer 啥的

nio.Unsafe 里的键盘 Signal 是不需要,也不会打断mainloop

八重 狐子:
因为我把那个function 直接suspend了

kt的async还真没怎么用过

duangsuse:
#bing
async{} 会返回一个 Deferred<T> 对象,表示协程的结果,可以通过调用 await() 方法
async{} 可以用来实现并发,即在同一个协程作用域中同时运行多个协程,并且等待它们的结果。
launch{} 则只是用来实现异步,即在后台运行协程,不需要等待它的结果1。

协程需要返回结果或并发,那么 async 可能更合适。 所以 async 只是用来延迟执行分组协程的?

延迟且有结果的 launch? 那和 ES6 async()=> 不一样啊, es6 没有说async是否并发吧..

好吧,是我理解有误 😅

isekiのChannel:
我这边写出的操蛋代码都长这样了: input.map{ async{ handle(it) } }.awaitAll()

duangsuse:
Promise.all(a.map()) 是正常操作
py asyncio.gather(x for a) 也一样

DOM 简直是UI UX 的天堂,我都不知道 Java 里还要手动定义阻塞线程(Disptacher)的 async 操作里

无所谓,反正标准库不会带,AI也不会写..
在 JavaScript 中,你可以使用 GPUBuffer.mapAsync() 方法来映射 GPUBuffer 的一部分,并且返回一个 Promise1。
在 Akka Streams 中,你可以使用 Source.mapAsync 或 Flow.mapAsync 来并发地运行多个 Future,并且保持元素的顺序2。
在 Python 中,你可以使用 multiprocessing.Pool.map_async 来非阻塞地运行多个进程,并且返回一个 AsyncResult3。

我误会 Python 了,虽然 asyncio 臭名远扬,
gather,wait,as_completed 在理论上比 Promise.all,race,any 准确

但是这种准确.. 真的不如js,至少有两个是保底记得住的
py可能还是败在箭头函数不好写,以及没有 libuv.org 那么异步的系统IO可攀,虽然 yield 是和js一样方便的,没有DOM那种免线程框架还是做不起来

Koshin:
平常写Android 业务的来说,基本这种就够了,我只在处理比较长的初始化流程用的上async

Yumeko:
在学dsl,是每创建一个方法都要存一个属性吗,不然好像没法用

Jason5Lee:
我甚至希望 HTML 本身就长这样(

duangsuse:
不过我最近打草稿的 JS 框架就是这样
Forwarded from dnaugsuz
#bing #py 移植到 scipy 和 cv2:

# wav2rawpng.sh
infile=$1
sox -r 44100 -b 16 -c 2 $infile -e unsigned -b 16 -c 2 test.raw
file=test.rgb
mv test.raw $file
# find out size in bytes
size=$(du -b $file)
echo size in bytes is $size
# calculate padding needed to ensure square image
# I don't even know what's going on with the 6's...
pad=$(awk -v size="$size" 'function quad(x){return(x*x)} function ceil(x, y){y=int(x); return(x>y?y+1:y)} BEGIN{ print quad(6*ceil(sqrt(size/6)))/6-size }')
echo padding in bytes is $pad
cp test.rgb test-pad.rgb
truncate -s +$pad test-pad.rgb

# oh yeah we need the resolution too
newedge=$(awk -v size="$size" 'function ceil(x, y){y=int(x); return(x>y?y+1:y)} BEGIN{ print ceil(sqrt(size/6)) }')
echo edge size is $newedge
magick convert -size ${newedge}x${newedge} -depth 16 test-pad.rgb ${infile%.wav}-rawpng.png

—失败
from scipy.io import wavfile
from PIL import Image
import numpy as np

rate, aud = wavfile.read('a.wav')

# Compute the minimum square dimension
l = int(np.ceil(np.sqrt(aud.size / 6)))
pad = int((l ** 2) * 6 - aud.size)

# Reshape the aud array into a square image
img = np.pad(aud, (0, pad), constant_values=0)
img = Image.fromarray(img.reshape(l, l, -1),'RGB')
img

import IPython.display as say

aud = np.array(img).reshape(-1)
aud = aud[:aud.size - pad]

wavfile.write('a1.wav', rate, aud)

say.Audio('a.wav')
#py #code #FP w2png diff
from PIL import \
Image ,\
ImageFilter as Filt
import \
librosa as sa, soundfile ,\
numpy as np ,\
functools as Fns

pipe=lambda*eq:Fns.reduce(lambda a,b:\
(lambda x:b[0](a[0](x)), lambda y:a[1](b[1](y))), eq)

def main():
cat,cut=w2bmp('a.wav') #v use blur(3px) on audio?
a=cat('out_'); cut(a)
b=cat('fi_').filter(Filt.GaussianBlur(radius=3)); cut(b)
display(a,b)

w2bmp=lambda fp:pipe(wav(fp), ft, (svA,svB), (np.flipud,np.flipud), bmp('HSV') )

def wav(f,sr=48000,ver=''):
def to(v): nonlocal ver;ver=v; return sa.load(f, sr=sr)[0]
return to, lambda y: soundfile.write(ver+f,y, sr,'PCM_16')

# A:w2bmp, B:bmp2w
bmp=lambda rgb: (
lambda A:Image.fromarray(A, mode=rgb).convert("RGB"),
lambda B:np.array(B.convert(rgb))
)

yMax,yPad=300,lambda x:np.pad(x, [(0, 1025-yMax)], 'constant')

ft=(lambda A:(F:=sa.stft(A)[:yMax], (np.abs(F),np.angle(F)) )[-1] ,\
lambda B:(lambda V,S:sa.istft(V * np.exp(1j * S)) )(*map(yPad,B)) )

def svA(A):
V,S=A; H=np.full(V.shape,0) # 0, power, phase
return np.dstack((H, S, V)).astype(np.uint8)
def svB(B):
H,S,V=(px[...,0] for px in np.dsplit(B,3))
return V,S


def main():
cat,cut=w2bmp, bmp2w
a=cat(); cut('out_',a)
b=a.filter(Filt.GaussianBlur(radius=3)); cut('fi_',b)
display(a,b)

# A:w2bmp, B:bmp2w
fp='a.wav'
sr=48000
yMax,yPad=300,lambda x:np.pad(x, [(0, 1025-yMax)], 'constant')

def w2bmp(): # 所以,你要在两个函数里涉及文件 read-write
A=sa.load(fp, sr=sr)[0]
F=sa.stft(A)[:yMax]
A=svA((np.abs(F),np.angle(F)))
A=Image.fromarray(A, mode="HSV").convert("RGB")
return A

def bmp2w(ver, B):
B=np.array(B.convert("HSV"))
V,S=map(yPad,svB(B))
B=sa.istft(V * np.exp(1j * S))
soundfile.write(ver+fp,B, sr,'PCM_16')
duangsues.is_a? SaltedFish
https://react.dev/blog/2023/03/16/introducing-react-dev 也写了 ee.Counter=({n=0})=>button( wOp({tap(){ n.v++ }}), Eq.fmt`pressed ${n}time$` //这样支持SSR或爬取 ) ee.Inp=({v="", isOk=$Y})=>html( input(wKV({v}) ) p(Eq.fmt`You typed: ${v}`), btn(Reset=>{v.v=""})…
ee.main=({name='world'})=>
h1(html`Hello ${name}!`)

ee.main=({src='rick.gif', name='Rick Astley'})=>
img(wKV({src, alt:html`${name} dancing`}))

ee.main=({n:0, hov})=>
button(
wSty({ $wtf: hov })
wOp({
tap(){ n.v+=1 }, hov
}, 'only'), //preventDefault
html`Clicked ${n}time$`
)

ee.main=({a=rn(0,10), b=a, c})=>(
Eq.at(c,{a,b}, _=>a+b),
div(
sel(a), sel(b),
p(html`${a}+${b}=${c}`)
)
)

ee.main=({n=0, n2,n4,sec}, my)=>(
Eq.at(n2, {n}, _=>n*2),
my.stop=CSS.s(0.5).rate(()=> n.v+=1),
div(
button(
wOp({tap: my.stop})
),
p(html`${n}*2=${n2}`),
p(html`${n2}*2=${n2(x=>x*2)}`)
)
)

ee.main=({n=0})=>(
Eq.at(n,{n}, _=>{
if(n>=10){ say(`count too high!`); return 9 }
})
button(
wOp({
click(ev){ n.v++ }
}),
html`Clicked ${n}time$`
)
)

ee.main=({t=0.})=>
html(
efx(t, {dur:400, ease:'k3'}),
progress(wKV({value: t})),
...rn(0,1, 1/4).lets(t=>button(
wOp({tap(){t.v=t}}),
html`${t}%`
))
)

ee.main=({vis=$Y})=>
html(
sel(vis),
p(efx(vis, {erase:{fly:{y:200,dur:2..s}, fade:{dt:.1} }}),
`in:fly out:fade`)
)

// 组件化
ee.main=()=>p(`Styled~`)
Nd.unit(CSS=>{
wSty("app")
wSty.p={
color: purple,
font: {
family: ['Comic Sans MS', cursive],
size: 2..em
}
}
})

ee.main=({it})=>(
wSty(it, "app"),
p(`These styles`, Nested())
)
ee.Nested=()=>
p(`...don't affect me `, html(`<u>here ULine</u>`))

ee.main=({})=>NeedKV(wKV({answer:42}))
ee.NeedKV=({ask:{answer}})=>
p(html`Universe is ${answer||'a mystery'}`)

const pkgs=[
{
name: 'svelte', ver: 3,
href: 'https://svelte.dev'
speed: 'blazing fast',
}
]

ee.main=()=>lets(pkgs, Info)
ee.Info=({name,ver,href,speed})=>p(html`
The ${code(name)} is ${speed}.
Get v${ver} from ${a(['',html`http:${name}`], `npm`)}
and ${a(['',href], `learn more here`)}
`)

//逻辑
ee.main=({
login=NO
})=>
when(login, {
$Y: btn(LogOut=>{ login.v^=1 }),
$N: btn(LogIn =>{ login.v^=1 }),
})

ee.main=({
x=7
})=>div(wOp({edit:$Y}),
when(x (x=>[x>10, x<5, $Y] ), [
p(html`${x} > 10`),
p(html`${x} < 5`),
p(html`${x} in rn(6,9)`),
]),
mark(wOp({edit:NO}), 'Truth: ',x, error)
)

let cats = [
{ id: 'J---aiyznGQ', name: 'Keyboard Cat' },
{ id: 'z_AbfPXTKms', name: 'Maru' },
{ id: 'OUtn3pvWmpg', name: 'Henri The Existential Cat' }
];

ee.main=()=>$app(
h1(`The Famous Cats of YouTube`),
lets(cats, ({id,name},i)=>
li(a(['',html`yt:${id}`,'_blank'], html`${i(Eq.num(+1))}: ${name}` ))
, ul(`empty?`))
)

let things = is.w`darkblue indigo deeppink salmon gold`.lets(
(x,id)=>({id,color:x}))

ee.main=()=>
html(
btn(Pop0=>{ things.splice(0,1) }),
grid({of:'1fr,2', gap:'1em'},
...['id',NO].lets(k=>
div(h2(`Key ${k}`),
lets(things.let({sort: k}), Thing)
)
)
)
)
duangsues.is_a? SaltedFish
ee.main=({name='world'})=> h1(html`Hello ${name}!`) ee.main=({src='rick.gif', name='Rick Astley'})=> img(wKV({src, alt:html`${name} dancing`})) ee.main=({n:0, hov})=> button( wSty({ $wtf: hov }) wOp({ tap(){ n.v+=1 }, hov }, 'only'), //preventDefault…
//Events, no forwarding indeed
ee.main=()=>html(
wOp({msg(ev) {ee.say(ev.text)} })
Inner({})
)
ee.Inner=({it})=>(
wOp(it.super={msg:1 }),
btn(sayHello=>{ it.super.msg({text:'morning!'}) })
)

ee.main=({d,time})=>(
Eq.at([d,time], [1..s.rate], ([t])=>[new Date, t]),
h1(html`Time is ${d}h24,${[,,,0,2,2]}`)
)

ee.main=({P=N2(0,0)})=>$full(
N2.ptr(P),
html`mouse @ ${P.x}y${P.y}`
)
ee.main=({x=0,y=0, k='client'})=>$full(
wOp({mousemove(ev) { x.v=ev[k.v+'X']; y.v=ev[k.v+'Y'] } }),
wOp({tap(){ee.say('Only once') } }, 'once'),
html`mouse @ ${x}y${y}`
)


api=ee.HI('tutorial/', {
'*':({text,ok})=> ok? text : Error(text)
})
ee.main=({F5})=>
html(
button(wOp({tap:F5}), `load Num`),
Reload({},
lets({load:[F5,api.random_number]}, x=>html`Rand num is: ${x}`)
)
ee.main=({F5})=>html(
button(wOp({tap:F5}), `load Num`),
Reload(
{load:p(`..Wait`),fail:p(wSty({fg:'red'}), error)},
lets({async*load() {
for(;; await F5) yield api.random_number()
}},
x=>html`Rand num is: ${x}`)
)
)

api=ee.HI('https://jsonplaceholder.typicode.com/', {
photos(x,{_limit}){}
})
ee.Photos=()=>
html(
h1(`Photos`),
grid({of: '5,1fr', gap:8}, wSty`full`,
lets({load:()=> api.photos(20) },
({thumbnailUrl:src, title:alt})=>figure(
img(wKV({src,alt})), figcaption(alt)
))
)
)

ee.main=({size=42, text='god', L})=>
html(
sel(size), sel(text),
p(html`size: ${L.x} h ${L.y}`),
div(
wKV({ xy:[0,L, 'absolute!'] }),
span(wSty({font:{size} }), text)
)
)

//Form
let active=a=>a.only({done:$N})
ee.main=({
todos=is.wdoc`
rewrite Svelte
build TODO app
adopt AI
`.split('\n').lets(x=> ({done:$N, text:x}))
})=>
html(
h1(`Todos`),
lets(todos, x=>div(wKV({show:x.done(q=>!q) })
sel(x.done), sel(x.text, {tip:`Do what?`})
)),
p(html`${todos([active,n])} remaining`),
btn(Add=>{ todos.add({done:$N,text:''}) }, Clear=>{ todos.let(active) ) })
)

ee.main=({pin=''})=>
html(
h1(wSty({ fg:pin(q=>q? '#333':'#ccc') }),
pin(x=>x? x.replace(/.(?!$)/g, '•') : 'pls enter' )),
Keypad({pin}, {submit:alert})
)

ee.Keypad=({pin}, my,
btr=(tap)=>button(wKV({show:pin(x=>!x)}), wOp({tap}))
)=>
grid({of:'3,5em 4,3em', gap:'.5em'},
wOp({of: 'button',
tap(){ pin.v+=this.innerText }
})
...rn(1,9).lets(x=>button(x)),
btr(()=> pin.v=''),
button(0),
btr(my.submit)
)

ee.main=({
name='',
ten=rn(0,10),
a=[1,ten],b=[2,ten],c,
yes=$N,
flavors=[['Mint choc chip'], menu],
scoops=[0, is.w`One Two Three`.lets(x=>x+' scoops')],
order='',
text='my **dear** Python'
})=>(
Eq.at(c, {a,b},_=>a+b),
Eq.at(order, {flavors,scoops},_=>
n(flavors)==0? 'need more!'
:n(flavors)>scoops? 'more scoops!'
:html`Ordered ${scoops}scoop$ of ${flavors}`.v
),
html(
sel(name,{tip:`enter your name`}), p(html`Helo ${name (x=>x||'stranger') }`),
sel(a, {chk:1}), sel(a),
sel(b, {chk:1}), sel(b),
p(html`${a}+${b} = ${c}`),
sel(yes),
when(yes,
{$Y: p(`Good boy!`),
$N: p(`Bad !! must be checked`) })
button(wKV({show:yes}), `Get Food`),

h2(`Size`), sel(scoops)
h2(`Flavors`), sel(flavors, {of:'many',chk:1}), // of:'' = select[multiple?]
order,

textarea(wKV({value: text}), wSty({width:'100%', height:200 })),
html(text(marked))
)

)
is.use`marked elizabot.Eliza`
let menu = [
'Cookies and cream',
'Mint choc chip',
'Raspberry ripple'
]

Rn.ptr
await 0..s
String.it({
swapcase(_) {
/[a-z]/.test(_)? toUpperCase():toLowerCase()
}
})



删掉了my参数,允许用 ee.fork 定义私有组件、直接添加原型链扩展。爽了,减少了UI设计的噪音

ee.Demo=({n=0, ptr,P}, fmt=({x,y})=>html`(${x},${y})` )=>
div(
wOp({ mousemove:ev=>ptr }), N2.ptr(P), ()=>其他初始化绑定,

btn(n, [html`++ ${n.to(x=>x+1)}time$`])
, b(wOp({tap:n.to(Eq.num(-1))}), `n--`)
p(ptr(fmt)),
li(P(fmt))
)

let localUI=ee.fork
ee.Demo.it({
__n1:_=> _.n+1,
n: Eq(x=>x+1)
})
我把文章的 #ts #Rust 代码重写了下

when- as
Automobile'wheels seats manufacturer'(:Cnt1, manu_:Str)

- main
Automobile(4,4,"X"):
say("My car has ${wheels} wheels and ${seats} seats, and it was made by ${manufacturer}.")

when- MyCar
Wheels Seats Manfus

- main
at car=[4 4 "X"].Ary
car[MyCar.Seats.id].as<Int>

“没什么语法把名字给编号,和类型对应,但 T() Send 可以实现T,Ln<Any>转换”
-! main
PairN<Cnt1 Cnt1 Str>([4 4 X]):[[Wheels Seats Manfus]]
Wheels

pkg @RowAsData
“tag和强转的就不写了,太智障。
struct True,False 的也算了,编译期计算没必要写成类型匹配”
when- Expr
Const(:Int)
Op(:Opk, A:Expr, B:Expr)
when- Opk
+ - * /

- +(e:Expr) = when e:
Const(x):x
Op(k,A,B): (+A to +B):
when k:
+: A+B

- main
at e: Expr = (+, (53), (-, (1), (0) ))
say(+e)

'AB'(get)when- Either
A(:A) B(:B)

at xx: Either.A<Int>
xx.as<Either<Int Any?>>

“data Nat = Z | S Nat deriving Eq ”

when- Nat
Z S(:Nat)
- +(:Nat) = when nat:
Z: this
S(x): S(this)+x
- + 'ab'(:Nat) = when a to b:
Z to n: n
S(x) to n: x+S(n)

- main
at:
one S(Z)
three (1~3) (Nat: Sum(Z,S))
one+three

-! printf(fmt:Str) = Fn1<Arg<Any>>{}.as<Fn>
^now
-! Fn = Type: “constexpr, TypeFamilies”
FnN(fmt('\\d'):Int )

动|静|绝句
Array 具名?元组,组 when-as,Ln<Str>
Tree union-和类型 when- HtmlNode
Value 具名?泛型 'T'type Ln, Any
for和递归 类型的归纳 'this'type Num
if和匹配 trait重写 - Str as() Int
签名 trait Fn<R> (编译期计算)
实现 impl Fn forT
调用 T as F<>::Out
#ts #PLT 每次看Py花猫的周刊,都能帮助自己改良设计…… 谈到 typed printf, 又不知绝句类型上什么写法最好了。 这些内容,可以理解为用“声明式“的方法 生成要eval() 的代码

- htmlTag("div", attrs..) 如何查到元素类型,和限制attr{k:v}
- int[10] 的 get(i), +int[5] 如何只在标准库实现
- pipe(num=Eq<Str Int>, aList=Eq<Int Any>) 如何得到 Eq<Str Any>, 或者提供 aList=Fn1:a[it] 的类型信息

绝句不会用上文里 C++,Rust 用的那种编译期模板,甚至比 Nim 的编译期计算走的更远。 -! evalFun(:Arg<*>)=arg[1] 本就是分段求值的

也就是通过监听已知参数上的执行,来推测「变量」的类型, at! kv=[:"a" 1 "b" 2.0] 这些“字典类型”也不需要专门做支持,因为'!'就是编译期内联的意思,只会在与变量同算式 或自身非:Send时,真正保留

这样看, -! printf(fmt:Str, :Arg<*>) = fmt('\\d').Ln:[regexSpan i] arg[i] 是不需要额外标注类型(函数)的,反正用了依赖类型,也只是把函数体 按「变量」而非「值」再复述一遍

高端在哪呢? 不过是 Box<T>,or:T, Fn1<T R> 的R既能从Box里推导,也能是抽象的<T>被listOf()组装 ,再查个重载。关系式编程并没有很难。
那么 int[10] 可表达为 'T'AryN(N:Cnt,:Ary) , fn(:AryN<Int>{N=10}), 构造和解构时检查下就好了,功能和纯函数式一样,还避免直接写 check() require()。

一些语言把递归匹配和类型运算符混在一起写 (都用上递归了,还不好做“反向查询”..),显得类型体操是个又难、又有用的技巧,但各个击破的话,这些强类型的魔法其实是没事找事…… 语言贫瘠造成的逻辑炸弹

但这样有问题,不能给 String.format() 标注类型;如果要的话,要组合出 Type: Fn1(Int, Str) 这种动态泛型 ,我不喜欢这种手动算类型的 ,但如何优化掉呢??
duangsues.is_a? SaltedFish
我把文章的 #ts #Rust 代码重写了下 when- as Automobile'wheels seats manufacturer'(:Cnt1, manu_:Str) - main Automobile(4,4,"X"): say("My car has ${wheels} wheels and ${seats} seats, and it was made by ${manufacturer}.") when- MyCar Wheels Seats Manfus …
#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)

at now: i 0
loop $Y:
breaks i<10
break i==100
say(i)
when i:
5: 这里才允许; break
else{}

太棒了,终于摆脱流控了!
但,正在考虑应该强制带上“跳过 跳出^0^” 以防止在单层循环体滥用

不少人在用 if continue 实现filter,但绝句会歧视过程式编程.. (0~9){>5}: say(this) 是绝句里单项和列表通用的搞法
"a arm bar ada".Sep.firsts{it[0]=='a': if !this{say("End")} } 则关于break

if break 可以视为 while(cond) 的扩充,但考虑CLI程序:
let:
at str=input("> ")
str:
in('(\d+)'):[[d]] say(d.Int+1)
loop(): str!="q"

二层循环(本该用函数跳转)

- Str find(sub:Str) Idx
at N=sub.Cnt
(0~Cnt-N):[i] //N=1,则 i=0~iLast
(0~~N):[iS]
break^0^ this[i+iS]!=sub[iS] //也可以每次iS=i 然后blabla..
return i
return -1

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

呃,这个是命题 all, any 的才能提前break

- Ln<Ln<Int>> firstZero
at now: i; j
this:[i a] a:[j x]
break^1^ x==0
say([i j])

应当把鸡肋的流控和过度return,扔进历史的垃圾桶了。 向物理公式看齐,而且没有数学的那些希腊字符,没有 __dunder__,但 +-*/ 都可由用户定义
比Py更激进,只有文件和(主语)函数域,不可以无缘无故加{}号分号

- move'ab'(:Int) = let:
loop(a-1,b+1): a!=0
b

'T'data Linked(x:T, xs:Linked?)
-'T' last(a:Linked) = a:
loop(xs): xs!=NO
x

fun move(a,b) = if(a!=0)move(a-1,b+1) else b

data class Linked<T>(val x:T,val xs:Linked<T>?)
fun<T> last(a:Linked<T>) = a.run { if(xs!=NO)last(xs) else x }
#blog 看到易语言还在VB++ 的范式旁徘徊,并且觉得编程语言是种必须特色和备案的「核心技术」… 我想复刻下这2007年文章的口吻:

“绝句.ju”十分钟入门教程
作者:转载必须注明出处

亲爱的朋友,您愿意花十分钟的时间,来了解一门全新的编程语言“绝句.未公开”吗?

#1
只有十分钟,时间紧迫,让我们立刻开始,不多说一句废话(这一句话本身算不算废话?哈哈)。
请去拜读易语言官方提供的《“易语言.飞扬”白皮书》——这本书写的很好,文笔比我强多了!本文大量参考该白皮书。

#2
绝句的大概:
- 物类面向对象,具有名词动词、同名例的概念(忘掉函数式编程吧
- 支持宿主语言的GC(Str Int 都是 Any 指针,能自动优化,轻松多了
- 源代码将被编译为全面西化的语言(当然还是比不上“仓颉”“木兰”了
- 用 data- JVM as 接口 跨平台编译为多个操作系统(微信OS/Homo/郭继承...)的可执行
- 可将源代码压缩为AST类库,以达到代码复用。
- 将会有一个包括“可视化函数设计”的集成开发环境(IDE),其将用js编写

我想有必要再强调一遍:“绝句”跟原来的Kotlin(1.x - 1.4.x)是完全不同的两个编程语言(如果非要找出相同点话,它们都能够用英文编程,作者都不是吴涛)

#3
物 启动类
同名例
- 起点
说("祖国您好!")

juc hello.ju_zh .java

启动类.class 的执行结果是在屏幕上输出:祖国您好!

还记得吗?吴涛教给我们的第一个易语言(旧版)程序不过是一句淡淡的问候而已,哪象“祖国您好!”这样饱含深情?
中国永远不缺少国际🇹🇼主义者,但我们急需的是 民族主义者🇨🇳

#5
类 游戏
- 猜

- 起点(猜:游戏=猜数字()) @JVM
猜去猜

物 猜数字 私下(内定数字 = 66) 游戏
|- 猜
重复 非(猜数字(“不可”)),。

- 猜数字()@私下 真假
在n=获取数()
说(n、 NL="")
回 判n去较(内定数字),
首中,说("猜对了,恭喜");真。
首大,说("太大了");假。
首小,说("太小了");假。

- 获取数 @可定 = 听("请猜1-100中的一个数:")去数

物 全自动猜数字 私下(可变_n=1) 猜数字()
|- 获取数 @终定 = n移右

#6
- 类是指接口,公开是一种注解
- 起点 启动 入口 主要 面 可以是文件函数
- 造于 私下(内定数字) 指明构造量
- 循环、如果 换成重复非、若判(表达式)了
- 继承和 Go 一样,写括号后面就好

#7
起点(全自动猜数字()) 自动用线性查找 内定数字
也可以改为 读:函0<数> 参数

#8
友好名称——用类自然语言格式书写程序:

'T'物 `将`(:T) “名记平权”
- 将<文>`写到屏幕` = 说(它)

- 起点
将123写到屏幕
100.123,[x]
(将x)写到屏幕

没想到吧,绝句记法还可以这么用😅
就是照着能解析Typst和bash设计的

三联判断式:

若x存于0~10, “如果(0 <= x <= 10)”
若x存于(0的右~10的左), “如果(0 < x < 10)”

多自然呀,为什么其它编程语言就是不支持呢?我想所有程序员学数学都早于学编程,(后面的太矫情,怕被喷就不复制了)

不知道 Python 是否后悔同时支持 range(A,B)和A<x<B ,那么在支持UI框架时, A<x<B 是等于两个滑条吗?

双向赋值运算符“<=>”:

在此刻,a 1;b 2
可变去换(a、b)
必,a是2 & b是1 “既然有解构 a,b=b,a 不就好了.. 绝句是有可变引用”

方法多返回值:

''名龄=俩项<文 计>
- 华夏=("中国"到5_000)

华夏(),[名到龄]
名去作<合法名>“require”
  FIXME "揣摩上意,是更喜欢讲中国台湾,还是给台湾打码"
必"🐭","🦆"!
FIXME "这不是国产OS吗? 上面为什么报错?"

/* FIXME(请领导指示): 台独检查的中文翻译 却有搞台独的风险 *///
''合法名=Str{ "台湾"!in this : "但这个没备案的境外苏联app搞台独啊"}


#9
有了Kotlin,为什么还要重新搞“绝句”?

Kt1.4 已经渐趋成熟和Java化,恢复正常的空间已经很小了。

……有哪些本质改进?

完全面向对象、自动垃圾回收、可自行开发类库、纯文本源代码(?)、多文件工程、与C/C++等语言水乳交(?)融。

已经有很多编程语言了,我们还需要一个全新的编程语言吗?

确实,汇编语言诞生时,C语言诞生时,C++诞生时,Pascal诞生时,Java诞生时,C#诞生时,都有人问这类问题

#10
改自全公网唯一剩下的易语言入门
404官方论坛:https://dywt.com.cn/vbs/

pkg
sys; random:rand
cmd:Cmd

- main=猜数字().cmdloop
data 猜数字(x=rand(1_000)/10)Cmd
made now:
数 0; 最接近 100
历史 [数 ]()
- `#$default`(ln)
ln.Int?{数=this}or: say()
历史 add 数; on(数)
- on(num)
num==x: say(); exit()
or:
say("太${(num>x).way("大","小")}了")
接近了(): say("不过接近咯")
- 接近了=历史(Sum: abs(x-it)).min:
Var.swap(最接近,this): return $Y
$N
静态解析外语的“jvm”函数签名 到 #TS
让GPT3 压行翻译到Prolog ,省掉了等号和infer
但参数是含变量的值,不是单变量,依然看起来很魔法

arg('', []) :- !. %前缀转列表前
arg('i'||'d'|Xs, [number|R]) :- arg(Xs, R).
arg('s'||'w'|Xs, [string|R]) :- arg(Xs, R).
arg('v'|Xs, ["ArrayBuffer"|R]) :- arg(Xs, R).
arg('b'|Xs, [bigint|R]) :- arg(Xs, R).
arg('p'|Xs, [bigint|R]) :- arg(Xs, R).

% 明明是样板代码,但AI仍然会写错
argF('', []) :- !.
argF('['||part||']'|Xs, [fnT<part>|R]) :- argF(Xs, R).
argF('i'||'d', [number|R]) :- argF(Xs, R).
argF('s'||'w', [string|R]) :- argF(Xs, R).
argF('v'|Xs, ["ArrayBuffer"|R]) :- argF(Xs, R).
argF('b'|Xs, [bigint|R]) :- argF(Xs, R).
argF('p'|Xs, [bigint|R]) :- argF(Xs, R).

resT('i'||'d', number) :- !.
resT('b'||'p', bigint) :- !.
resT('_', void) :- !.

fnT(args, (Xs, number | void)) :- arg(args, Xs).

fnKV(args||'!'||res, Args, R) :- argF(args, Args), resT(res, R).
fnKV(args, Args, void) :- argF(args, Args).

relocated需要{}类型,GPT不会用Prolog查表
duangsues.is_a? SaltedFish
静态解析外语的“jvm”函数签名 到 #TS 让GPT3 压行翻译到Prolog ,省掉了等号和infer 但参数是含变量的值,不是单变量,依然看起来很魔法 arg('', []) :- !. %前缀转列表前 arg('i'||'d'|Xs, [number|R]) :- arg(Xs, R). arg('s'||'w'|Xs, [string|R]) :- arg(Xs, R). arg('v'|Xs, ["ArrayBuffer"|R]) :- arg(Xs, R). arg('b'|Xs, [bigint|R])…
duangsuse:
#js #web #Svelte 还没用熟 TypeScript 社区已经开始抛弃了 - 零点CoCo的文章 - 知乎
https://zhuanlan.zhihu.com/p/626237877

看起来他们比我还激进? (虽然我也是观望,不会为TS专门改设计

我是这么看的,前端也就只有123和abc, [{}] 三个类型

标注太占地方,还不如直接用 {a=0} 或者清晰的名字, EQ 简化了UI部分,让JS函数绑定到一种XML模板,消除了很多人眼障碍
如果编程习惯好的话,没有检查应该不会怎么样

本来以为Svelte这个作者算有两把刷子的,没想到和我的观念相似……

无虚拟 DOM 版 Vue 进行到哪一步了? - 手撕红黑树的文章 - 知乎
https://zhuanlan.zhihu.com/p/644340806

为什么React一年不发新版了? - 魔术师卡颂的文章 - 知乎
https://zhuanlan.zhihu.com/p/642766301

(现在AI的智商感觉越来越低了,不知还能不能用来给项目加类型)

JS的常量级类型check是很弱的, 比C好一点

DOM能有什么复杂的API ,都是RPC级别的类型复杂度, TS除了做点{}[] 的类型函数 好像也不需要计算很多


#FP 纯函数: 数据皆静止,调用皆惰性:(ok? print : noOp) 的if只是函数, if 必须有 else 。不可以用匹配&重构外的方式计算, 用"单子" "幺元" 结构来做流控
if let 解构,只要”值可以含可变<T>“ 👀,就变成简单的构造器&异常=跳过
可理解为”只能添加(调用) 不能反查“的关系式
子类型接口:
#haskell 使用解耦的 class (Num t) -instance (Num Int) 实现调用按类型,就像 #kt fun T.run(:重载)=按T单分派 ,会比 when-is 好
Visitor 可以把”覆写“隔离成配置对象 map({Int x: x+1, Str:}, 语法树), 连”配置“也是可继承&扩充的

反射:在弱类型里元编程才算直观, Object.values(AnyType) 在 Java就是所谓反射了。
Str的同名例TYPE,包含 f(_隐式this)(arg); _.x; _["x"]=1 的”语法“的实现。 KV<Str Int>.typedArg[0] 同是类型
Str 除了属于Type,还可遍历成员做 toJSON, 0参创建,依赖注入(=按类型.ini) 等接口
@定义() 如果只能生成为传参,就等效于在构造器调用 get("/http") {} 或继承钩子