Skip to content

Instantly share code, notes, and snippets.

@duangsuse
Created December 1, 2024 05:18
Show Gist options
  • Save duangsuse/3674d747ec5ea8ca510add26295e5a7d to your computer and use it in GitHub Desktop.
Save duangsuse/3674d747ec5ea8ca510add26295e5a7d to your computer and use it in GitHub Desktop.
脚本语言上想做「非侵入async」,很简单,问题是时延和错误边界的明确性。
#!ipy -i
def cat():
x=yield '1st'
while True:
x=yield x
z=cat(); next(z) #x=() 待执行
[z.send(n) for n in range(10)]
'''
有人说 async def 是“红色”,因为不能在蓝的REPL和“带参数脚本”里call它们
没错,async就是允许你setTimeout(retAddr,0s)并return的空函数,你们叫它yield或await。
这样一切回调地狱都能用 await new Promise(ret=> timers.push(1s,ret)) 解决,不是吗?
能捕获当前语句/算式号为变量的(ret)叫函续。等返回值卡线程,if分1段执行不完,就必须用 div(10,5,ok), div.bind(10,0)(ok,err) 的回调链表代替调用-返回栈
当然,赋值 global(ThreadLocal) or arg(vueUse) 也行。call-return 还有很多玩法,AOP hook、fndefGC(摇树)、taint污点参数分析和火焰图等等。 fire.py httpie 则是命令行版函数。
脚本语言上想做「非侵入async」,很简单,问题是时延和错误边界的明确性。
come on, 在函参可以随意增长的py里,你没发现 def: yield 和 def: return 这两种调用-返回结构共用“一个颜色”吗?
https://gist.github.com/BeautyyuYanli/0a6891d8959bcf06b5cd2e5bd30ef3d1
^^ 认为移植一下 TJ Holowaychuk/co.js 就能bypass这个“红色”问题?其实忽视了设计哲学。
下面我展示下如何从语法上隐藏async的差异,就像那 def: yield 和 def: return
'''
import asyncio as IO
Ctrl=lambda k: wait4(get_ipython().pt_app.key_bindings.add(f'c-{k}'))
fname='''
def wait4(needCb):
needCb((out:=IO.Future()) .set_result)
return out
def vscode():
await Ctrl('k')
await Ctrl('f')
print("close dir!")
'''
import ast as et
def autoAsync(e):
e=et.parse(e)
iLn=[]
class FindAwait(et.NodeTransformer):
def visit_FunctionDef(self, f):
if any(isinstance(e, et.Await) for e in et.walk(f)): dd(iLn.append)(f.lineno-2)
return f
FindAwait().visit(e)
return sedI(et.unparse(e), iLn,'async ')
sedI=lambda s,ai,pre: "\n".join((pre+x if i in ai else x) for i,x in enumerate(s.split('\n')))
dd=lambda f: lambda*a: (v:=f(*a),print(v,*a),v)[-1]
exec(dd(autoAsync)(fname))
get_ipython().pt_loop.create_task(vscode())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment