V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
ca1123
V2EX  ›  程序员

我已经完全是 recurse 的形状了, 有老哥 Clojure 玩的比较六的么?

  •  
  •   ca1123 · 2022-07-08 02:19:11 +08:00 · 2946 次点击
    这是一个创建于 905 天前的主题,其中的信息可能已经有所发展或是发生改变。

    希望能有偿咨询一下, 虽然这是我写的最顺的语言, 但还是有很多问题. 希望找人交流一下.

    26 条回复    2022-08-02 23:08:19 +08:00
    rpman
        1
    rpman  
       2022-07-08 02:34:10 +08:00
    写 ClojureScript 的给你顶一下 🐶
    wdv2ly
        2
    wdv2ly  
       2022-07-08 07:47:23 +08:00 via Android
    来我司入职吧🐶后端唯一指定开发语言
    ymmud
        3
    ymmud  
       2022-07-08 08:15:04 +08:00
    感觉 clojure 的热度大不如前
    HENQIGUAI
        4
    HENQIGUAI  
       2022-07-08 09:08:24 +08:00
    我记得 Leancloud 好像挺喜欢 Clojure 的
    ca1123
        5
    ca1123  
    OP
       2022-07-08 09:17:59 +08:00
    @rpman 我是搞不定前端, burn-out 的太快了.
    ca1123
        6
    ca1123  
    OP
       2022-07-08 09:18:30 +08:00
    @HENQIGUAI 有所耳闻
    ca1123
        7
    ca1123  
    OP
       2022-07-08 09:22:21 +08:00
    @ymmud lisp 这种描述操作过程的, 和现在流行的统计学习这一套确实不搭. 不过手写 AST 可以最大限度同态于自己的思维, 以前写 java, js, python, wolframe, matlab, 写着写着就不知道自己在干什么了. clojure 也会晕, 但是看看结构 8 成能想起来当时在干什么. 只要习惯了迭代, 还是很爽的.
    ca1123
        8
    ca1123  
    OP
       2022-07-08 09:23:14 +08:00
    @wdv2ly 贵司是搞 FinTech 的?
    FaiChou
        9
    FaiChou  
       2022-07-08 09:41:32 +08:00
    ```
    (defn interpereter [expr env]
    (if (list? expr)
    (let [[p1 p2 p3 p4] expr]
    (match [p1 p2 p3 p4]

    ['if pred true-branch false-branch ]
    (if (interpereter pred env)
    (interpereter true-branch env)
    (interpereter false-branch env))

    ['* arg1 arg2 nil]
    (* (interpereter arg1 env) (interpereter arg2 env))

    ['dec arg nil nil]
    (dec (interpereter arg env) )

    ['zero? param nil nil]
    (zero? (interpereter param env))

    [func params nil nil]
    ((interpereter func env) (interpereter params env))

    ['fn [x] body nil]
    (fn [arg]
    (interpereter body (fn [y]
    (if (= x y)
    arg
    (env y)))))

    :else (assert false (str "未能捕获 list:" expr))))
    (match [expr]
    [(n :guard symbol?)] (env n)
    [(n :guard number?)] n
    :else (assert false (str "未能捕获元素:" expr)))))

    (interpereter '(((fn [!]
    (fn [n]
    ((! !) n)))
    (fn [!]
    (fn [n]
    (if (zero? n)
    1
    (* n ((! !) (dec n)))))))
    5)
    (fn [e] (assert false (str "no such element.." e) )))
    ```
    FaiChou
        10
    FaiChou  
       2022-07-08 09:42:57 +08:00
    ymmud
        11
    ymmud  
       2022-07-08 10:03:55 +08:00
    @ca1123 玩过,在公司没法用
    zhuangzhuang1988
        12
    zhuangzhuang1988  
       2022-07-08 10:16:15 +08:00
    太动态了 ide 不友好
    直接学 F#好还有 Fable 写前端.
    ca1123
        13
    ca1123  
    OP
       2022-07-08 10:21:27 +08:00
    @FaiChou 写各种求值器是很爽, 我看 Y 组合子的时候, 虽然匿名 recur 起来, 这个能接受, 但是最终的 arg 怎么送进去的, 还是有点蒙古. 感觉你可以整个更吊的, 把 if 也换成丘奇定义 IFTHENELSE := λp.λa.λb.p a b

    另外, 我正好问你个问题, 宏展开的时候, 怎么把作为参数的 s-exp 组合到宏的模板里面, 然后再一股脑求值. 而不是把 s-exp 用~解了 syntax quote 以后就不管了.
    比如

    ```
    (defmacro println-test [form]
    `(println ~form))

    (let [form `(+ 3 1)]
    (println-test form))

    ```
    我不要
    ```
    (clojure.core/+ 3 1)
    => nil
    ```

    我想要
    ```
    4
    => nil
    ```

    有不用 eval 的办法么, 套两层 defmacro 行么?
    ca1123
        14
    ca1123  
    OP
       2022-07-08 10:22:51 +08:00
    @zhuangzhuang1988 是的, 已经感觉到了. 但是我觉得我写 java 写着写着就迷失了, 就是因为 ide 指挥我怎么写代码
    ca1123
        15
    ca1123  
    OP
       2022-07-08 10:24:58 +08:00
    @ymmud 我是野路子出身, 本身是学应用数学的, 对 C 文化有点接受不能.
    wdv2ly
        16
    wdv2ly  
       2022-07-08 11:59:31 +08:00 via Android
    @ca1123 游戏公司
    Dregs2
        17
    Dregs2  
       2022-07-08 12:21:49 +08:00 via Android
    @wdv2ly 贵司在哪里呀ʕ•ٹ•ʔ
    Dregs2
        18
    Dregs2  
       2022-07-08 12:27:59 +08:00 via Android
    我之前也研究了好久,好像如果不用 eval 编译评估的话就要手动评估,宏应该只是在编译期生效,对于动态传入的 list 好像没法做到这种效果。
    ca1123
        19
    ca1123  
    OP
       2022-07-08 15:04:14 +08:00
    @wdv2ly 我本科学物理的
    ca1123
        20
    ca1123  
    OP
       2022-07-08 15:14:16 +08:00
    @Dregs2 你说的对, 出现在 macro 定义里面的函数当场就求值了, 不会等到运行时. 在 runtime 里面, unquote 的时候, 这个部分处理过了, runtime 就去看别的地方了, 不会关注处理出来的值是不是还要求值, 就不会再处理了, 就相当于一个 quote. 我想要的是先 unquote, 和模板拼好, 然后再求值, 所以应该用 macroexpand-1 和参数上的 unquote 让 runtime 先拼模板, 模板拼好了, 一股脑丢给 eval 就行了. 主要是看别人说 eval 不好, 少用, 但是 eval 能用的特殊情况中其中一个用法就是 runtime 才知道参数内容.
    1hscj3sm63
        21
    1hscj3sm63  
       2022-07-08 16:14:54 +08:00
    clj 搞一些函数式运算,还有研究宏造 DSL 还是很爽的,不过感觉平时业务都是搬砖,不太用的上
    Dregs2
        22
    Dregs2  
       2022-07-08 17:38:56 +08:00 via Android
    你发的例子中
    (let [form `(+ 3 1)]
    (println-test form))
    form 已经是是一个 list
    在宏里面能拿到的也是这个 list ,没法通过宏来展开,运行时评估看起来还是得用 eval
    ca1123
        23
    ca1123  
    OP
       2022-07-08 20:25:24 +08:00
    @1hscj3sm63 我哭死, 我写不来 C 系的语言, 都是谭浩强的错
    ca1123
        24
    ca1123  
    OP
       2022-07-08 20:25:58 +08:00
    @Dregs2 是, macro 会把整个 list 对应到一个 symbol 上去, 只 resolve 一次
    ca1123
        25
    ca1123  
    OP
       2022-07-10 09:11:53 +08:00
    @Dregs2 我今天又怼了一天 macro, 自定义 macro 组装 go-loop, 里面还有<!和作为传进来参数的 channel. 人都麻了. clojure 还真是有点问题, 数据结构上, 不像其它 lisp 是封闭的, clojure 很多数据本质是 java 对象, 包括语言本身的要素, 正向求值 fn 的时候没问题. 但是在 macro 里面如果, 就不能形成 clojure 代码的 closure. 如果 var 里面是一个 java object, 它也可以 unquote, 但是 eval 不认... 这时候就得手操 dynamic var, 或者 intern symbol, 或者 laziness (如果这个 object 其实是 clojure 代码产生的), 把 macro 里面 eval 要用的数据套一个 clojure var 的形式, eval 这个东西, 还不接受 lexical binding, fn 参数符号和 let 的符号都不认. 不过这个用 macro 接收 s-exp 拼一个能运行的 form 的目的总算有点眉目了.
    wdv2ly
        26
    wdv2ly  
       2022-08-02 23:08:19 +08:00 via Android
    @Dregs2 坐标深圳
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2457 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 89ms · UTC 02:38 · PVG 10:38 · LAX 18:38 · JFK 21:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.