lambdex - 让 Python 支持更复杂的 lambda 匿名函数表达式 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
hsfzxjy
V2EX    分享创造

lambdex - 让 Python 支持更复杂的 lambda 匿名函数表达式

  •  4
     
  •   hsfzxjy
    hsfzxjy 2021-02-10 14:19:56 +08:00 2690 次点击
    这是一个创建于 1761 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先放出 Github 地址: https://github.com/hsfzxjy/lambdex

    大概一个月前有一个奇思妙想:说到匿名函数,Python 虽有 lambda 表达式,但与其他语言如 Rust 的闭包或是 JS 的箭头函数相比还是过于简单了。其函数体仅支持单一表达式,不支持更复杂的语句。我想对此做一些扩展,使 Python 支持更复杂的匿名函数。于是便有了 lambdex 。

    目前 lambdex 支持写出类似如下的代码(以递归计算 Fibonacci 数列为例):

    from lambdex import def_ def_(lambda n: [ if_[n <= 0] [ raise_[ValueError(f'{n} should be positive')] ], if_[n <= 2] [ return_[1] ], return_[callee_(n - 1) + callee_(n - 2)] # Recursion ])(10) # 55 

    lambdex 以一种非侵入式的方式在运行时转写 AST 并编译成字节码,并将字节码缓存以供后续使用,因此只有首次编译的 overhead 。同时,lambdex 还提供了一个内置的 Formatter,用于格式化含有匿名函数的代码。

    也许你会说“这个库没有工程应用价值” “这个库不 Pythonic” “这个语法不够函数式”等等。本人认同这些观点。

    但作为一个语法扩展的实验性项目,lambdex 应该算是同类中较为完备的。lambdex 本身有很大的可玩性,并为实现其他语言中的一些函数式范式提供了可能。

    lambdex 确实不 Pythonic,但对于不看重 Pythonic 的用户,这是个好的尝试。同时 lambdex 对标的是如 Rust 或 JS 中的匿名函数,期望在匿名函数中提供更完备的 imperative programming 体验,并无意向 Haskell 等看齐。

    最后个人认为构建这个库本身就是一件很有趣的事情。在这个过程中本人接触到了 CPython 底层的许多细节,同时也在不断思考如何更干净地实现各种逻辑。这是非常有意义的一件事。

    欢迎各位试用并提 Issues !

    16 条回复    2021-02-11 14:23:50 +08:00
    abersheeran
        1
    abersheeran  
       2021-02-10 15:21:21 +08:00
    很酷!我详细看看。另外一提,在类似于循环中使用 def_(lambda x: ...) 会不会反复创建匿名函数对象?
    hsfzxjy
        2
    hsfzxjy  
    OP
       2021-02-10 15:29:12 +08:00
    @abersheeran 不会哦,只有第一次循环时会编译,其他时候会利用缓存
    abersheeran
        3
    abersheeran  
       2021-02-10 15:35:46 +08:00
    @hsfzxjy 那么这个缓存的失效时机是?
    abersheeran
        4
    abersheeran  
       2021-02-10 15:38:10 +08:00
    能否开开 GitHub 的 discussions,v2ex 的提醒我有时候会看不到,GitHub 的提醒比较及时。另外在 GitHub 上讨论也便于后来者查看。
    flgn88
        5
    flgn88  
       2021-02-10 15:41:37 +08:00 via iPhone
    额,lambda 本身不就是为了方便实现简单功能而无需单独定义一个 method 吗?一家之言仅供讨论哈
    hsfzxjy
        6
    hsfzxjy  
    OP
       2021-02-10 15:42:53 +08:00
    @abersheeran #3 在整个运行时中不会失效。被缓存的仅仅是函数的 code object,不包含函数的上下文,因此是比较轻量的。循环中调用 def_,或者是在一个函数中返回 def_,都会复用同一个 code object 。
    hsfzxjy
        7
    hsfzxjy  
    OP
       2021-02-10 15:44:20 +08:00
    @nuistzhou #5 你说的有道理,但是有时候我们可能需要一些复杂却又是一次性的逻辑,这时 lambda 就显得有些捉襟见肘了。
    abersheeran
        8
    abersheeran  
       2021-02-10 15:44:58 +08:00
    @hsfzxjy 明白了。
    122006
        9
    122006  
       2021-02-10 16:09:24 +08:00
    我也写了一个 java 支持内插字符串的语法糖。
    一堆人畏之如虎。推广真的太难了
    hsfzxjy
        10
    hsfzxjy  
    OP
       2021-02-10 16:19:38 +08:00
    @abersheeran #4 刚看到这条,已开了 Discussions ~
    hsfzxjy
        11
    hsfzxjy  
    OP
       2021-02-10 16:21:39 +08:00
    @122006 #9 哈哈,所以我选择在 README 和推广帖里先自我批评一下
    abersheeran
        12
    abersheeran  
       2021-02-10 16:42:41 +08:00   3
    @122006 嗨,有趣的东西不要直接给中国程序员群体推。去国外推,在国外火了,自然有人上赶着给你搞汉化。

    这是我看华人最强开源项目运营大师(作品:Vue )的一些经历和发言。加之自己的观察得出来的观点,或有错漏,但不妨一试。
    hsfzxjy
        13
    hsfzxjy  
    OP
       2021-02-10 21:11:58 +08:00
    刚添加了新的特性,完整支持了 async/await 系列的语法。同时也添加了若干可选的语言扩展,如 Rust 风格的 await,自动返回最后一个表达式。
    shniubobo
        14
    shniubobo  
       2021-02-11 09:59:14 +08:00 via Android
    @hsfzxjy #7 既然复杂了,为什么不直接定义一个函数呢?即便是一次性的逻辑,也完全可以单独定义一个函数;这样既可以把这个逻辑单独分开,让代码更清晰,还可以在 traceback 里面显示函数名。
    hsfzxjy
        15
    hsfzxjy  
    OP
       2021-02-11 14:21:36 +08:00
    @shniubobo #14

    一个场景是在写高阶函数时,我们通常要将被返回的写成 nested function这种方式见仁见智,但个人感觉是不够直观的。

    此外,对于**稍微**复杂点的 predicate,比如稍微多一两个分支,或者需要暂存某些中间结果,这种放入 lambda 会降低可读性甚至放不进 lambda,单独存一个具名函数个人觉得没有必要。此外还有 GUI 编程中,如果 event handler 的逻辑简单但不能表达成 expression,lambda 不使用,但也没必要单独拎一个函数。这些都是 lambdex 优于 lambda 的可能场景。

    至于 traceback 和 函数名,lambdex 是可以做到的。lambdex 的编译和运行时错误可以精确定位到相应的行,未来也会支持让函数具名(但这个名字不会暴露到它的父级作用域),可以说 debug 的体验和普通函数是一致的。

    个人认为,Python 官方推荐的范式是好的,但也没必要把相关的 anti-patterns 视为洪水猛兽,有时它们会是更优的选择。当然个人也不提倡滥用某个 pattern,这个库也不是为了这个目的提出来的,只是希望能在有人需要它们时提供可行性。
    hsfzxjy
        16
    hsfzxjy  
    OP
       2021-02-11 14:23:50 +08:00
    @hsfzxjy #15 lambda 不使用 -> lambda 不适用
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3462 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 04:39 PVG 12:39 LAX 20:39 JFK 23:39
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86