热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Elixir-动态调用私有函数

如何解决《Elixir-动态调用私有函数》经验,为你挑选了2个好方法。

我发现Kernel.apply/3它允许通过将方法指定为原子来动态调用模块中的公共方法,例如result = apply(__MODULE__, :my_method, [arg])转换为result = my_method(arg)

困扰我的是一种称私人方法的方法; 给出这样的代码:

defmodule MyModule do
    def do_priv(atom, args) when is_list(args) do
        apply(__MODULE__, atom, args)
    end

    # (change defp => def, and this all works)
    defp something_private(arg), do: arg #or whatever
end

我希望这MyModule.do_priv(:something_private, [1])是允许的,因为它是从模块内部调用私有方法.我可以理解,引擎盖Elixir正在使用Erlang的apply/3,所以这种方法可能不会让我们在那里.

我也试过使用这个Code.eval_quoted/3方法,但它似乎甚至没有能够调用硬编码的私有方法(因此没有时间花在手上构建AST,而不是quote do像下面那样使用 - 尽管如果有人看到这是一个选项如何使这项工作):

defmodule MyModule do
    def do_priv_static do
        something_private(1) #this works just fine
    end

    def do_priv_dynamic do
        code = quote do
            something_private(1)
        end
        Code.eval_quoted(code, [], __ENV__)   #nope.  fails
    end

    defp something_private(arg), do: arg #or whatever
end

同样,它可以从包含模块中访问私有函数,所以我希望它是允许的.它可能我只是不明白__ENV__参数eval_quoted

唯一可行的解决方案,现在正在改变defpdef,这是我个人的代码精解; 但是既然我编写的代码支持其他关心的程序员,我想找到一个解决方案.

我对其他方法持开放态度,但我个人难以理解如何实现这一目标.



1> sasajuric..:

在Erlang中不能动态调用AFAIK私有函数(因此不能在Elixir中).如果需要进行动态分派,可以考虑使用多子句功能.一个人为的例子(肯定是一个糟糕的例子,但想不出更好的ATM):

iex(1)> defmodule Math do
          def operation(op) do
            IO.puts "invoking #{inspect op}"
            run_op(op)
          end

          defp run_op({:add, x, y}), do: x + y
          defp run_op({:mul, x, y}), do: x * y
          defp run_op({:square, x}), do: x * x
        end

iex(2)> Math.operation({:add, 1, 2})
invoking {:add, 1, 2}
3

iex(3)> Math.operation({:mul, 3, 4})
invoking {:mul, 3, 4}
12

iex(4)> Math.operation({:square, 2})
invoking {:square, 2}
4

另一个选择是公开您的功能,但表明@doc false它们是内部的 - 即不打算由客户公开​​使用.您还可以考虑将这些功能移动到单独的模块中,并将整个模块标记@moduledoc false为内部模块.两种方法偶尔用于Elixir代码中.

但是我建议开始简单,并使用模式匹配+多子句函数.如果代码变得更复杂,我会考虑其他选项.



2> Miroslav Pry..:

首先,您应该知道f()在MyModule模块中MyModule.f()调用的内容与在同一位置调用的内容不同.见http://www.erlang.org/doc/reference_manual/code_loading.html#id86422

您只能调用私有函数f()样式.这些调用也由编译器检查 - 如果该函数不存在,则会出现编译错误.当你MyModule.f()在同一个地方使用时,你不会得到编译错误,因为这些调用只在运行时检查(即使你从内部调用模块),效果是(AFAIK)就像你MyModule.f()从任何一个调用一样其他模块 - 在运行时查找模块,您只能调用导出(公共)函数.

因此,您不能以任何其他方式调用私有函数,而不仅仅是普通函数f().apply(mod,fun,[])mod.fun.()样式的等价物- 模块在运行时解析,私有函数不可访问.

您可以在此示例中自行尝试所有变体:https://gist.github.com/mprymek/3302ff9d13fb014b921b

你现在可以看到,在编译时必须始终知道对私有函数的调用,所以你甚至不能使用eval_quoted魔法或任何其他魔法来使它们"动态"......

Sasa Juric的使用建议@doc false是正确的解决方案.


推荐阅读
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在安装 iOS 开发所需的 CocoaPods 时,用户可能会遇到多种问题。其中一个常见问题是,在执行 `pod setup` 命令后,系统无法连接到 GitHub 以更新 CocoaPods/Specs 仓库。这可能是由于网络连接不稳定、GitHub 服务器暂时不可用或本地配置错误等原因导致。为解决此问题,建议检查网络连接、确保 GitHub API 限制未被触发,并验证本地配置文件是否正确。 ... [详细]
  • Visual Studio Code (VSCode) 是一款功能强大的源代码编辑器,支持多种编程语言,具备丰富的扩展生态。本文将详细介绍如何在 macOS 上安装、配置并使用 VSCode。 ... [详细]
  • 解决问题:1、批量读取点云las数据2、点云数据读与写出3、csf滤波分类参考:https:github.comsuyunzzzCSF论文题目ÿ ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在Ubuntu系统中安装Android SDK的详细步骤及解决“Failed to fetch URL https://dlssl.google.com/”错误的方法
    在Ubuntu 11.10 x64系统中安装Android SDK的详细步骤,包括配置环境变量和解决“Failed to fetch URL https://dlssl.google.com/”错误的方法。本文详细介绍了如何在该系统上顺利安装并配置Android SDK,确保开发环境的稳定性和高效性。此外,还提供了解决网络连接问题的实用技巧,帮助用户克服常见的安装障碍。 ... [详细]
  • 解决针织难题:R语言编程技巧与常见错误分析 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • 计算机视觉领域介绍 | 自然语言驱动的跨模态行人重识别前沿技术综述(上篇)
    本文介绍了计算机视觉领域的最新进展,特别是自然语言驱动的跨模态行人重识别技术。上篇内容详细探讨了该领域的基础理论、关键技术及当前的研究热点,为读者提供了全面的概述。 ... [详细]
  • 本文介绍了如何在 Windows 系统上利用 Docker 构建一个包含 NGINX、PHP、MySQL、Redis 和 Elasticsearch 的集成开发环境。通过详细的步骤说明,帮助开发者快速搭建和配置这一复杂的技术栈,提升开发效率和环境一致性。 ... [详细]
  • 今天我开始学习Flutter,并在Android Studio 3.5.3中创建了一个新的Flutter项目。然而,在首次尝试运行时遇到了问题,Gradle任务 `assembleDebug` 执行失败,退出状态码为1。经过初步排查,发现可能是由于依赖项配置不当或Gradle版本不兼容导致的。为了解决这个问题,我计划检查项目的 `build.gradle` 文件,确保所有依赖项和插件版本都符合要求,并尝试更新Gradle版本。此外,还将验证环境变量配置是否正确,以确保开发环境的稳定性。 ... [详细]
  • 【图像分类实战】利用DenseNet在PyTorch中实现秃头识别
    本文详细介绍了如何使用DenseNet模型在PyTorch框架下实现秃头识别。首先,文章概述了项目所需的库和全局参数设置。接着,对图像进行预处理并读取数据集。随后,构建并配置DenseNet模型,设置训练和验证流程。最后,通过测试阶段验证模型性能,并提供了完整的代码实现。本文不仅涵盖了技术细节,还提供了实用的操作指南,适合初学者和有经验的研究人员参考。 ... [详细]
author-avatar
蚂蚁少校
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有