gpt4 book ai didi

macros - 双 Clojure/ClojureScript 库设计和宏

转载 作者:行者123 更新时间:2023-12-04 23:58:23 25 4
gpt4 key购买 nike

假设我有一个库 xx,其命名空间为 xx.core ,我用纯 Clojure 编写它,打算同时针对 Clojure 和 ClojureScript。这样做的实际方法似乎是使用 lein-cljsbuild’s crossovers and conditional comments .到现在为止还挺好。 这个前提现在已经过时了。 lein-cljsbuild 已被弃用,取而代之的是 reader conditionals ,还有许多其他命名空间/宏 ClojureScript 增强功能。见updated answer以下。

假设 xx 有一堆变量,我希望它的用户能够在 Clojure 和 ClojureScript 中使用。这些可以分为三种类型的变量。

  • 不依赖 xx 中的宏的函数/其他 var(我将这些称为 type-1 var)
  • 恰好发生的函数/其他变量依赖于 xx 中的宏(我将称之为 2 类变量)

  • 但是,由于 ClojureScript 要求将宏与常规 .cljs 分开。命名空间在他们自己的特殊 .clj命名空间,所有宏必须与 xx.core 中的所有其他变量隔离开.

    但是其中一些其他 var(type-2 var)的实现偶然地依赖于这些宏!

    (可以肯定的是,使用 ClojureScript 的 use-macrorequire-macro 似乎只能访问宏。刚才我对此进行了测试;我尝试将所有内容(宏、type-1 vars 和 type-2 vars)简单地保存在一个单一的 xx/core.clj 文件,并在 ClojureScript 测试文件中使用 (:use-macro xx.core :only […]) 引用它。然后编译器为 ClojureScript 文件引用的 WARNING: Use of undeclared Var 中的每个非宏变量发出 xx.core 消息。)

    在这种情况下,人们倾向于做什么?在我看来,我唯一能做的就是……将库的公共(public) API 拆分为三个命名空间:一个用于类型 1 变量,一个用于宏,一个用于类型 2 变量。像…… xx.core , xx.macro , 和 xx.util ?…

    当然,这很糟糕,因为现在 xx 的任何用户(无论是在 Clojure 还是 ClojureScript 中)都必须知道每个 var(可能有几十个)是否在其实现中碰巧依赖于一个宏,以及它因此而依赖于哪个命名空间属于。如果我只针对 Clojure,这将是不必要的。如果我想同时针对 Clojure 和 ClojureScript,这真的是现在的情况吗?

    最佳答案

    这个问题的前提在几年前基本上已经过时了。通过这次更新,我正在尽自己的一份力量,不要让过时的信息污染网络。

    与 Clojure 不同,ClojureScript 通常在与运行时分开的编译阶段编译宏。还有很多附带的复杂性。但是,由于多项改进,情况已大大改善。

    version 1.7 in 2015 , Clojure 和 ClojureScript 现在支持 reader conditionals ,它允许在同一个 .cljc 中定义宏和函数Clojure、ClojureScript、Clojure CLR 或所有三个文件:#?(:clj …, :cljs …, :cljr …, :default …) .仅此一项就可以缓解大部分问题。

    此外,ClojureScript 本身现在对 ns 进行了多项增强。这为命名空间的用户消除了许多其他附带的复杂性。它们现在记录在 Differences from Clojure, § Namespaces 中。 .它们包括隐式宏加载、内联宏规范和自动别名 clojure命名空间:

    Implicit macro loading: If a namespace is required or used, and that namespace itself requires or uses macros from its own namespace, then the macros will be implicitly required or used using the same specifications. Furthermore, in this case, macro vars may be included in a :refer or :only spec. This oftentimes leads to simplified library usage, such that the consuming namespace need not be concerned about explicitly distinguishing between whether certain vars are functions or macros. For example:

    (ns testme.core (:require [cljs.test :as test :refer [test-var deftest]])) will result in test/is resolving properly, along with the test-var function and the deftest macro being available unqualified.

    Inline macro specification: As a convenience, :require can be given either :include-macros true or :refer-macros [syms…​]. Both desugar into forms which explicitly load the matching Clojure file containing macros. (This works independently of whether the namespace being required internally requires or uses its own macros.) For example:

    (ns testme.core
    (:require [foo.core :as foo :refer [foo-fn] :include-macros true]
    [woz.core :as woz :refer [woz-fn] :refer-macros [apple jax]]))

    is sugar for

    (ns testme.core
    (:require [foo.core :as foo :refer [foo-fn]]
    [woz.core :as woz :refer [woz-fn]])
    (:require-macros [foo.core :as foo]
    [woz.core :as woz :refer [apple jax]]))

    Auto-aliasing clojure namespaces: If a non-existing clojure.* namespace is required or used and a matching cljs.* namespace exists, the cljs.* namespace will be loaded and an alias will be automatically established from the clojure.* namespace to the cljs.* namespace. For example:

    (ns testme.core (:require [clojure.test]))

    will be automatically converted to

    (ns testme.core (:require [cljs.test :as clojure.test]))`


    最后,ClojureScript 现在有了第二个目标:引导的、自托管的 ClojureScript,也就是 CLJS-in-CLJS。与 CLJS-on-JVM 编译器相比,引导的 ClojureScript 编译器实际上可以编译宏!分离仍然在源文件中强制执行,但它的 REPL 可以将它们与函数混合运行。

    Mike Fikes 就 Clojure–ClojureScript 可移植性的这些和其他问题撰写了一系列有值(value)的文章,同时这些功能正在开发中。这些包括:
  • “Portable Macro Musing”, 2015
  • “Messing with Macros at the REPL, 2015
  • “ClojureScript Macro-Functions”, 2015
  • “ClojureScript Macro Tower and Loop”, 2015
  • “ClojureScript Macros Calling Functions”, 2016
  • “ClojureScript Macro Sugar”, 2016
  • “Collapsing Macro Tower”, 2016

  • 即使在 2017 年,看到 ClojureScript 继续成熟也是令人兴奋的。

    关于macros - 双 Clojure/ClojureScript 库设计和宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13835031/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com