如何在 ClojureScript 中运行 eval 并访问调用 eval 的命名空间?

2024-05-11

我有一个函数库,我想让用户在浏览器中使用它。

所以我想设置这样的情况:

我正在使用 Figwheel 和 devcards 进行开发。

在主要的 core.cljs 我require我的库中的各种函数,所以它们都在范围内。

现在我想让用户输入一些调用该库的代码。

我知道如何使用 eval 运行该代码,但我不知道如何使我的库函数对正在评估的代码可见。

我对我看到的大多数有关此问题的文档感到困惑(例如如何使函数可用于 ClojureScript eval? https://stackoverflow.com/questions/50828008/how-can-i-make-functions-available-to-clojurescripts-eval)

是否可以?如果是这样,有人有一个简单的例子吗?

cheers

Phil


是的,可以提供对评估代码使用的环境/预编译库的访问。

首先,您必须确保库中的函数在 JavaScript 运行时可用。换句话说,避免:advanced优化,因为这将消除编译时 (DCE) 未调用的函数。自托管 ClojureScript 兼容:simple.

其次,您需要使分析元数据可供将在浏览器中运行的自托管编译器使用(可以使用cljs.js/load-analysis-cache!或可选参数cljs.js/empty-state).

下面是一个说明如何执行此操作的最小项目(也位于https://github.com/mfikes/ambient https://github.com/mfikes/ambient):

项目代码

src/main/core.cljs:

(ns main.core
  (:require-macros [main.core :refer [analyzer-state]])
  (:require [cljs.js]
            [library.core]))

(def state (cljs.js/empty-state))

(defn evaluate [source cb]
  (cljs.js/eval-str state source nil {:eval cljs.js/js-eval :context :expr} cb))

(defn load-library-analysis-cache! []
  (cljs.js/load-analysis-cache! state 'library.core (analyzer-state 'library.core))
  nil)

src/main.core.clj:

(ns main.core
  (:require [cljs.env :as env]))

(defmacro analyzer-state [[_ ns-sym]]
  `'~(get-in @env/*compiler* [:cljs.analyzer/namespaces ns-sym]))

src/library/core.cljs:

(ns library.core)

(defn my-inc [x]
  (inc x))

Usage

我们有一个main.core命名空间提供了一个evaluate函数,此示例将展示如何在环境/预编译中调用函数library.core命名空间。

首先,通过以下方式启动浏览器 REPL

clj -m cljs.main

在 REPL 中,通过评估来加载我们的主命名空间

(require 'main.core)

测试我们是否可以评估一些代码:

(main.core/evaluate "(+ 2 3)" prn)

这应该打印

{:ns cljs.user, :value 5}

现在,自从main.core必需的library.core,我们可以调用该命名空间中的函数。在 REPL 上对此进行评估将产生11:

(library.core/my-inc 10)

现在,让我们尝试使用自托管 ClojureScript 中的这个“环境”函数:

(main.core/evaluate "(library.core/my-inc 10)" prn)

你会看到以下内容

WARNING: No such namespace: library.core, could not locate library/core.cljs, library/core.cljc, or JavaScript source providing "library.core" at line 1
WARNING: Use of undeclared Var library.core/my-inc at line 1
{:ns cljs.user, :value 11}

简而言之,正在发生的事情是,尽管library.core.my_inc在 JavaScript 环境中可用,并且确实可以被调用,产生正确的答案,您会收到来自自托管编译器的警告,表明它对此命名空间一无所知。

这是因为编译器分析元数据不在main.core/state原子。 (自托管编译器有自己的分析状态,在 JavaScript 环境中保存在该原子中,它与 JVM 编译器分析状态分开,在 Java 环境中通过 Clojure 保存。)

注意:如果我们有源library.core由自托管编译器编译(也许通过使用main.core/evaluate评估"(require 'library.core)",以及正确定义cljs.js/*load-fn*可以检索此源代码,事情会很好,并且编译器分析元数据would be in main.core/state.但这个例子是关于调用环境/预编译函数library.core.

我们可以通过使用来解决这个问题cljs.js/load-analysis-cache!加载与关联的分析缓存library.core命名空间。

此示例代码通过使用从基于 JVM 的编译器抢夺分析缓存的宏,将此分析缓存直接嵌入到代码中。您可以通过任何您想要的机制将此分析缓存传输到浏览器;这只是说明了一种简单地将其直接嵌入到运输代码中的方法(它只是数据)。

继续评估以下内容,只是为了看看该命名空间的分析缓存是什么样的:

(main.core/analyzer-state 'library.core)

如果你打电话

(main.core/load-library-analysis-cache!)

该分析缓存将被加载以供自承载编译器使用。

现在如果你评估

(main.core/evaluate "(library.core/my-inc 10)" prn)

您不会看到任何警告,并且将打印以下内容:

{:ns cljs.user, :value 11}

此外,由于自托管编译器现在具有以下分析元数据libraray.core,它可以正确警告数量错误,例如

(main.core/evaluate "(library.core/my-inc 10 12)" prn)

将导致打印:

WARNING: Wrong number of args (2) passed to library.core/my-inc at line 1

上面说明了当命名空间不存在分析器缓存时会发生什么以及如何修复它cljs.js/load-analysis-cache!。如果你知道你总是想在启动时加载缓存,你可以简单地使用一个可选参数cljs.js/empty-state在初始化时加载此缓存:

(defn init-state [state]
  (assoc-in state [:cljs.analyzer/namespaces 'library.core]
    (analyzer-state 'library.core)))

(def state (cljs.js/empty-state init-state))

其他的项目

一些(更详细的)项目使库函数可用于浏览器中自托管的 ClojureScript:

  • 巴朗迈斯特 https://github.com/ctford/klangmeister
  • 动力龟 https://github.com/timothypratley/power-turtle
  • 生活演示 https://github.com/quoll/life-demo
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 ClojureScript 中运行 eval 并访问调用 eval 的命名空间? 的相关文章

  • 在 Clojurescript 中查找不匹配的分隔符

    有时我会发现自己遇到大括号 圆括号或方括号不匹配的情况 在 Clojurescript 中 我在用leininingen and cljsbuild我很难追踪到错误源 通常它可以归结为这样 Compiling resources publi
  • <%# Eval("State") %> 或 <%# DataBinder.Eval(Container.DataItem, "state")%>

    拥有和拥有有什么区别 in your aspx页面 与具有 in your aspx page Eval State 是一个简化形式DataBinder Eval Container DataItem State 句法 它仅适用于数据绑定模
  • 如何从命名空间内重载运算符<<

    这是我能想到的最小的包含示例 首先是类的标题 每当使用 pragma once ifndef EURO H define EURO H include
  • Python 中 eval("input()") 和 eval(input()) 之间的区别

    我正在尝试以下功能 x eval input 输入为 123 x 的类型也是int 它工作正常 In 22 x eval input enter enter 123 In 24 print type x
  • 如何在 bash 中结合超时和 eval 命令

    为了执行存储在变量中的命令eval使用命令 gt a echo e a nb wc l gt eval a 2 但如何才能与它结合起来呢 timeout命令 我尝试过以下操作 这给了我错误的输出 gt timeout 10 a a b wc
  • 使用 Javascript eval() 100% 安全吗?

    我正在编写一个生成 Javascript 代码的 PHP 库 Javascript 代码有许多名为component001 component002 etc 页面通过 AJAX 动态加载 我需要通过 URL 变量传递组件的名称 然后由脚本进
  • 我可以将 Dojo 名称空间更改为 dojo 以外的名称空间吗?

    我知道你可以使用 jQuery noConflict 为 jQuery 做到这一点 有没有办法用Dojo做类似的事情 我相信你可以 看这一页 http dojotoolkit org reference guide quickstart m
  • 如果没有定义命名空间,类将拥有什么命名空间

    在 C 中 如果我创建一个没有命名空间的类 那么在尝试实例化该类时将使用哪个命名空间 例如 假设 main 是 namespace NamespaceTests class Program static void Main string a
  • 获取函数的命名空间

    我正在开发一个包 我希望在其中向对象添加编辑历史记录 该包允许其他包注册用于编辑对象的函数 我正在寻找一种方法来记录注册用于编辑的函数的包的版本 问题是 给定一个函数 如何从导出的位置获取包 我的想法是调查它的搜索路径 但是search 仅
  • Rails 路线、url 和子域

    我的 ruby 应用程序分为不同的命名空间 例如 免费 free domain com 专业版 pro domain com vip vip domain com 在路由文件中看起来像这样 namespace free do match h
  • 在 C# 中使用命名空间别名有什么好处? [复制]

    这个问题在这里已经有答案了 使用命名空间别名有什么好处 仅仅是为了简化编码吗 仅当与类发生冲突时我才使用名称空间别名 对我来说 这根本没有简化 我的意见是 如果没有必要 就不要使用
  • JQuery 命名空间 + 通用实用函数的最佳实践

    目前有哪些 经验法则 为了实施JQuery 命名空间托管通用实用函数 我有许多 JavaScript 实用方法分散在各个文件中 我想将它们合并到一个 或多个 命名空间中 最好的方法是什么 我目前正在研究两种不同的语法 按优先顺序列出 JQu
  • 将表达式捕获为 R 中的函数体

    我正在尝试编写一个程序 该程序将表达式作为输入并返回一个以该表达式绑定作为其主体的函数 caller lt function expr params Function lt function params body env parent f
  • 在javascript中计算字符串值,而不是使用eval

    有没有一种方法可以在不使用 JavaScript 的情况下计算存储在字符串中的公式eval 通常我会做类似的事情 var apa 12 5 9 9 4 2 console log eval apa 那么 有谁知道替代品eval 嗯 你可以使
  • 在命名空间 { } 块中屏蔽#include?

    编辑 我知道方法 1 本质上是无效的 并且可能会使用方法 2 但我正在寻找最好的 hack 或更好的解决方案来缓解猖獗的 可变的命名空间扩散 我在一个命名空间中有多个具有不同依赖关系的类或方法定义 并且希望使用尽可能少的命名空间块或显式范围
  • 在 PHP 中调用用户定义的函数 eval()

    我一直在使用 eval 函数进行 php 测试 但 eval 似乎无法正确调用用户定义的函数 请看我的例子 function equals a b if t r return true else throw new Exception ex
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • PHP 类中的命名空间和全局变量问题

    我陷入了这种困惑 我不明白为什么我的 HelperClass 下的全局 error 返回空 我可以验证 class gt error 确实之前已填充了数据 在这种情况下 命名空间是否存在某种我不知道的问题 请给我一些指点 以下是一些相关的代
  • 如何将 Python 标识符转换为数字?

    参考 有没有更快的方法将数字转换为名称 https stackoverflow com questions 11052808 在上面提到的问题中 找到了将数字转换为名称的解决方案 这个问题问的恰恰相反 如何将名称转换回数字 到目前为止 这就
  • 未命名命名空间与全局声明

    使用未命名命名空间和全局声明有什么区别 使用这两个有什么特定的上下文吗 我们可以访问外部源文件中未命名的命名空间组件吗 未命名命名空间的要点是在翻译单元 源文件 内提供唯一的命名空间 而不需要显式前缀 这可以让您保证您的全局名称不会与其他翻

随机推荐

  • 如何将 UILabel 与个人资料照片图像水平对齐?

    我必须显示名称和电子邮件 ID 与个人资料图像正确水平对齐 这样姓名和电子邮件 ID 就出现在 UIImageView 的中心 但您可以看到姓名和电子邮件 ID 不在个人资料图片的中心 为什么会发生这种情况 我给出了以下限制 删除前导和尾随
  • 如何使用 Nuxt ServerMiddleware 和 Apollo GraphQL 处理 301 重定向

    我目前正在构建一个 Vue Nuxt 应用程序 并结合修改后的 Saleor 安装来在线销售产品 当我们从现有系统迁移时 我们需要能够处理从旧网站 URL 到新网站 URL 的 301 重定向 我修改了 API 以响应以下 GraphQL
  • 将图片添加到图库 - Android

    我有一个活动 用相机拍照 然后将其添加到正确的文件夹 在本例中为 DCIM Camera 但是当你退出应用程序并加载 Android 图库时 它不在那里 我正在玩一些游戏 发现它只在重新启动手机后才出现 我不确定这背后的原因 也许它必须创建
  • 如何避免在 webpack 生产构建中重复模块“bn.js”?

    我的应用程序使用了 webpack 4 不知何故 bn js包在生产构建中占用了大量资源 从图中可以看出 它占用了594 22KB 数据 有没有办法让1个文件bn js对于所有依赖于的包bn js 发生这种情况可能是因为您的依赖项都需要不同
  • 禁用选择标签内的一个选项值在 IE6Ha 中不起作用[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个包含 4 个值 a b c d 的选择框 我只想禁用下拉列表中的 c 我使用了禁用属性 它在所有浏览器中都有效 但在 IE6
  • 在 pyproject.toml 的动态字段中使用 python 脚本生成的值

    我试图找到一种使用 pyproject toml 内的 python 脚本生成的值的方法 例如 假设我们有一个函数random version 我正在使用 setuptools 来构建包 import random def random v
  • 从 jQuery 事件访问函数中的参数*和*事件

    这是我不久前问的另一个问题的后续问题 通常 您可以从 jQuery 事件的函数调用中访问事件 如下所示 item live click functionToCall 并在函数中 function functionToCall ev do s
  • 为什么 std::shared_ptr 实现中需要两个指向托管对象的原始指针?

    这是 cppreference 的实现说明部分的引用std shared ptr 其中提到有两个不同的指针 如粗体所示 可以通过get 以及在控制块内保存实际数据的一个 在典型的实现中 std shared ptr仅保存两个指针 存储的指针
  • 在 R 中捕获段错误

    我得到了caught segfault每次我尝试从以下位置运行任何绘图函数时都会出错ggplot2包 1 0 0 我已经尝试过这个qplot geom dotplot geom histogram等来自包的数据 例如diamonds or
  • Python SQLite SELECT LIKE IN [列表]

    如何在Python中编写SQL查询来选择Python列表中的元素 例如 我有 Python 字符串列表 Names name 1 name 2 name n 和 SQLite table 我的任务是找到最短路线 SELECT element
  • Python选择列表中最长字符串的最有效方法?

    我有一个可变长度的列表 并且正在尝试找到一种方法来测试当前正在评估的列表项是否是列表中包含的最长字符串 我正在使用Python 2 6 1 例如 mylist abc abcdef abcd for each in mylist if co
  • 使用 buildSchema 时如何访问字段解析器内父解析器的值?

    当我们使用 graphqlHTTP 时 传递给解析方法的第一个参数实际上是客户端查询传递的参数 而不是 root 这对于查询解析器来说很好 但是对于字段解析器需要知道父级值的用例 如何实现这一点 type Person name Strin
  • Flutter中如何在弹出屏幕后调用函数更新值?

    屏幕 1 显示带有添加按钮的项目列表 屏幕 2 用于将新项目添加到列表的表单 屏幕 2 gt gt 屏幕 1 在屏幕 2 中调用 navigator pop 时 如何在屏幕 1 中调用方法 setState 更新列表 谁能帮我吗 我不想再次
  • 在 Visual Studio Code 中调试 Strapi

    我正在尝试在 VS Code 中调试我的 Strapi 项目 3 0 0 beta 16 6 我的启动 json type node request attach name Attach to strapi port 9229 我的pack
  • Ruby Regex 舍入尾随零

    我正在寻找一个正则表达式来删除十进制数字中的尾随零 它应该返回以下结果 0 0002300 gt 0 00023 10 002300 gt 10 0023 100 0 gt 100 1000 gt 1000 0 0 gt 0 0 gt 0
  • Office JavaScript API:突出显示文档中的文本

    我正在使用 Microsoft Office JavaScript API 开展一个业余项目 我一直依赖着文档 https learn microsoft com en us office dev add ins reference jav
  • 是否可以使用谷歌地图从坐标获取地址?

    我只是好奇 也许是为了未来的项目 我想知道是否可以通过 Google API 从给定坐标检索地址 是的 只需使用 Google 地理编码和 Places APIhttps developers google com maps documen
  • vuejs 延迟加载组件,无需路由器

    vue 中的延迟加载组件使用 webpack 并不困难 https alligator io vuejs lazy loading vue cli 3 webpack https alligator io vuejs lazy loadin
  • leaflet.draw 垃圾按钮删除所有多边形并保存

    使用javascript 如何更改leaflet draw 垃圾桶 按钮以删除所有已绘制并自动保存的多边形 下面是我实现的代码 但它是一个完整的黑客 它会删除活动多边形 但是在删除对象后 当我单击 垃圾箱 图标时 控制台中开始出现错误Not
  • 如何在 ClojureScript 中运行 eval 并访问调用 eval 的命名空间?

    我有一个函数库 我想让用户在浏览器中使用它 所以我想设置这样的情况 我正在使用 Figwheel 和 devcards 进行开发 在主要的 core cljs 我require我的库中的各种函数 所以它们都在范围内 现在我想让用户输入一些调