duangsuse::Echo
717 subscribers
4.26K photos
130 videos
583 files
6.48K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
Forwarded from Airsaid
implementation 是 runtime,那么 runtimeOnly 又是?
天哪。 #android #java
反正我只爱 DOM 和 Model/View
Forwarded from no13bus
现在大家用aac架构的多吗?怎么看这个架构
Forwarded from no13bus
Android architecture components
Forwarded from no13bus
这个跟mvvm mvp mvc相比,是不是复杂了
Forwarded from 工藤 新一
但是啊,我的配置已经是4G了:
Forwarded from Fei Yang
@AntiRevoke
請幫忙檢舉謝謝(
Report > Other
範文:
This channel provides a "plugin" for tdesktop that breaks the delete message feature for other chat members, this plugin violates clause 1.4 of telegram's api tos, please ban this channel.
Forwarded from Shen Wenlin
雖然的確違反 API ToS 但它不是一個用戶端
#Telegram 另:喜闻新 Channel Comment 功能产生
借着这个官方手刃同人的机会,咱来谈一谈 Channel comment board 应该怎么写。

这里不提及回调、消息队列、按钮盘和内联之类的细节,只写成接受必要参数的 fun onXXX() 的形式

与 Telegram 的数据交流与存储责任优先提及:
inline keyboard 各钮的文本和 callback ID 由tg保存,回调含 targetMessage

bot PM(private message) 含事件 onMessageEdited, onMessageDeleted

单单实现添加评论很简单,在按钮链至PM /start 后提示用户输入,再更新目标消息、插入"${user.name}: ${msg.text}"即可。

不过这个流程会被打断成 inline-button 存 targetMessage 再 pm 得检查关于 user 的 state (1参, targetBoard) 才能做到收到后更新。

这个状态表优化后就是 Map<UID, MID>
可以设计为 UserState: add(u,v) get(u) pop(u) 的形式

onKeyboardCallback(msg,key) = state.add(msg.user, msg)
onMessage(chat,msg) if (chat.isPM)
msg.command == "start" -> if (state.get(msg.user) != null) /*提示*/
state.pop(msg.user)?.let { /*更新board*/ }

如果要支持编辑/删除消息操作,必须进行一定程度的关系型数据库建模。
因为文本是由 board 保存的,可以仅对 board msgId : PM msgId 实际储存,从而能在 PM 删除时 getBoardMsg

Board(channelId, msgId)
hasMany PM(msgId)

顺便存 chan. Id 也无所谓,如果实现 channel 的 board 枚举用得到

至于编辑可以实现 parse:(String) -> Map<UID, String> 操作和对应的 toBoardText() 操作,当然也可以直接 String.modifyBoardText(i, text)

以字符串保存列表必须处理转义问题(比如单项的换行符必须保留,人类可读,就可以用 "\n(.*):  " 切分而替换单项的文本,不过在 tg 里用 bold mark 标注用户名就可以了),但这样还是比独立存储文本再去拼合的开销低。

但仅这样还差一点:不知道要修改的是第几条。假设一个 board 同 user 只能有一条评论,可以再建立一个记录 Board hasMany BoardUser(no, user) ,或者如果 SQL 扩展支持数组的话,直接保存用户ID数组

必须保存创建编号来升序排列,而可 indexOf 查出编辑消息用户的位置,不过这样也就可以同时做一个『最近评论』页了…… (以编号降序,某人在某板评论了 board.findPM(/**/) )

毕竟关系数型据库的 record 除了 "relation" 外也称为 "entity"

当然,更正经的做法是直接保留 PM 的创建顺序,然后查某pm在某board里的位置(pm.board/*findBoard()!!*/.indexOf(pm)),上面是提示思维过程。

关系型数据库的名字可不是白叫的,它不是像 CSV 一样,仅仅像 ORM(object rel. mapping) 一样是 List<T> ,尽管它所支持的“关系”非常初步,而且基于 foreign key,只有 hasOne/hasMany 以及 relation "wtf" 的双边关系。
今天早上胡思乱想了一会,给一个写起来节约空间,基本上算英文绝句初版的 AtScript (为啥东西设计的现在提了也没用) 弄了个有意思的缩进语法:

thing WTF were
  fun init() = noOp()
  val layout = verticalLayout:
    text("emmm")
    button()

这个英文版的结构是 class/thing/insta/fun 用 were, for/while/if/when 用 do , 闭包用 do |a,b| 。

这个利用分号的语法也是为了节约击键次数(为此里面的类型都是 Bool,IntX+Idx+Cnt,Char,Str 这样)设计的特殊调用参数列表语法,有了它应该还可以结合 optional 参数,拿来写 DOM:

import markup.html.*
root = body:
  script(src="wtf.js")
  div(css="list"):
    a("#", "link")

print(Document:
  head(title("bad"))
  root)


实现什么的不用担心啦,就是在 o.x, o[i] 和 o() 左递归链后面加料(:) 呢。

说起来,如果 o() 不在左递归链里,而是把 o.op() 解析为 GiveSelf(o, Call("op", [])) 也是可以的,但是和底层不太对仗也容易搞混优先级,不过优点是可以写出 o.!contains(x) 这种基于函数变换的表达式(就有点像 Elixir 的 |> railway 了),哈哈。

不过重点不是这个。我打算给这么语言支持 suspend function (也就是 coroutine)

实现起来并不困难,扩充于 FunctionAst 建立一个 CoFunctionAst 就好了,里面嵌套的 CoFunc.invoke 也靠 instanceof 判断能提供 指令指针栈的 resume 信息, CascadeMap+LexicalBinding 就能保留闭包数据,可惜只能做到 Python/ES6 的语句级别保留执行状态。

其实我对 coroutine 是不了解的,除了知道 Lua 是非对称协程(只能将执行权转交给 resume 者的协程)、 ES6 的 await/async 和 co 的 Promise/Thunk(返回“收回调”函数的函数) 是由将 suspended 协程(下片也即其“回调”部分)交给其之前 yield 的 Promise 的方式来解决回调嵌套外,不知道具体的利用方法(如序列化、 "suspend fun" 的封装)。

为此我去问同写 Kotlin 的冰封哥,Kotlin 的协程为什么会有"Scope",答复是“CoroutineScope 是 CPS 变换的 Context” (CPS, continuation passing style, 传递函数进程的手段),我一直没弄懂这个上下文到底是咋用的,它和 Scoping 又有没有关系。

CPS 可理解为上面 ES6 await/async 二者一起(await=yield, async=co) 进行 await op1(); op2() 变执行实为 op1(() => op2()) 的手段

我不解的是,如果 continuation 是传递回,那必须 capture 住整个栈,但传递上是不需要的。
如果 Kotlin 的 CPS 就是把 o.await() 前的部分交给 o ,复苏 continuation 就仅需 return 到调用栈某一层因为栈上已经保留了所需信息,为什么会需要 CoroutineIntrinsics 的 create,resume,suspendOrReturn 三基元呢?
这种方法能实现 Sequence(即 generator) ,看起来它比协程高级,那么它到底和被数据化的子程序状态(coroutine)有什么关系?

百思不得其解,于是我打算以我懂的 ES6 generator 来实现(缺点是只能把 yield 建模为语句而不是函数)

但是我仍想用三基元,而且还是想让 yield 函数去带参 suspend 当前协程。

结果我发现了一个问题,导致我有点理解了 Kotlin 的设计:协程挂起后该由谁恢复?

suspend fun s123 were
  yield(1); yield(2); yield(3)

(老实说 #Kotlin 的“无需分号化”也有点迷, println(1) println (2) 算不算中缀调用说不清)

上例 s123() 挂起了可以得到当前项,最后可以抛 StopIteration 之类(或作为 resume() 返回值),可是假设我是要实现 Iterator 而必须有 next/hasNext ,从而我得保留 1项的流不变视口,在语言内部自然是不适合处理(为扩展性)

于是我想到了 fun sequence(builder: suspend BuilderScope.() -> T) 收的函数类型,其实有 BuilderScope.yield

这样你可以把 sequence builder 直接表达为 Iterator :

var lastItem: T? = runCatching { resume(builder) }.getOrNull()
// 只是举个例子, T:Any? 也可独立出 var hasLast
fun hasNext() = lastItem != null
fun next() = lastItem.also { /**/ }


明白了,那么 delay(1000).await() 也就可以理解为 Scope 里的 ext fun Async/*Deferred*/<Unit>.await() ,这也就解释了 Kotlin 支持 local fun 却不支持其 with receiver 是因为仅 class 级别可以。

它和协程对象本身的关系就是:(制定一个顺序,这里举例回调)

runOp(callback={ resume(this@Scope) })

结合星野大佬的经验 http://blog.hoshino9.org/2018/12/31/paint-board.html

var timer = GlobalScope.async { delay(1000) }
fun main() = runBlocking {
println("begin")
timer.await()
timer = async { delay(3000) }
println("finshed")
}

据说 runBlocking 会在所有内部 coroutine 执行后返回,所以此程序在 timer= 时阻塞,要改正只需换回 GlobalScope.async 。

await 本身也算协程,感觉应该很奇怪,但这是必须的。
假设没有任何 CPS 编译优化, op.await() 就应该是把当前上下文(协程状态)交给 op 以待其 resume ,所以 await 当然是非阻塞的,而且它会将当前协程挂起 (suspend fun)
方便。原来就想 Cloudflare workers 可以拿来托管 bot 🤔
Forwarded from Soha 的日常 (Soha Jin)
刚才给本频道添加了一个关联群组,那么以后本频道就有评论区了!(鼓掌👏
但那个群组只是为了启用评论功能而设置的,所以请不要加入。如需评论,请直接点击频道内推文下方的评论按钮(没有按钮的话就请升级到 Telegram 的最新版本),那个功能不需要加入群组也可以正常使用。
如果加入了那个群,会被机器人踢出并封禁 1 天,被封禁的时候评论功能也是不可用的。
至于为什么这么做已经在上一条推文中提过了。
机器人用到的代码公开在这里
#Linux #freedom Telegram BLUG shut 了🤔
Forwarded from BLUG Username Hold
请各位订阅者如有需要,左转到主站 https://beijinglug.club 和聊天室。谢谢茄子~
Forwarded from 螺莉莉的黑板报
https://deno.land/x/cat_you/
奇葩 deno 模块大赏:cat_you,提供一个 API 可以生成随机的猫咪 ASCII Art。
#迷惑行为大赏
是啊, 23+2 mod 24 = 1 位置记数法进制问题的确很基础,然后乘法表什么的的确扯,就是 (1..9)./*flat*/map { a -> (1..9).map { b -> if (b>a)/*(1*9==9*1)*/ "" else "$a×$b = ${a*b}"} } 嘛,不稀奇呢
Forwarded from 螺莉莉的黑板报
「正确的讨论方式」