有时我们需要动态生成一些模块名,然后调用它里面的函数。但是我们常常碰到的却是明明有那个模块,结果还是raise模块未定义。。。

我们来看看到底怎么回事?

首先我们定义一个函数

iex(1)> defmodule Science.Math do
...(1)> def add(x,y) do
...(1)> x + y
...(1)> end
...(1)> end

当我们正常调用它是,是没有问题的:

iex(2)> Science.Math.add 1,2
3

但是

iex(3)> t= "Science.Math"
"Science.Math"
iex(4)> :"Science.Math".add(1, 2)
** (UndefinedFunctionError) undefined function :"Science.Math".add/2 (module :"Science.Math" is not available)
:"Science.Math".add(1, 2)

为什么明明有的模块却没找到呢?

因为我们定义的模块其实应该是:"Elixir.Science.Math", 而不是:"Science.Math"

所以我们应该使用

iex(5)> (t|> String.split(".") |> Module.concat).add(1,2)
3

但是Module做String to Atom的转换时用的是:erlang.binary_to_atom(string, :utf8)

如果在运行期间大量调用这个函数可能造成原子数耗尽(erlang的atom是不回收的)

所以我们还可以使用Module.safe_concat/1

iex(5)> (t|> String.split(".") |> Module.safe_concat).add(1,2)
3

safe_concat使用的 :erlang.binary_to_existing_atom(string, :utf8).

这解决了上面这个函数的风险,但是也引入别一个可能,有可能输入的string是一个系统从来没有exist的atom就会crash掉。

如果我们只是想调用"Nested.Foo.Test"模块里面的函数, 还可以再用一种巧妙的方式。

iex(6)> t = "Science.Math"
"Science.Math"
iex(7)> :"Elixir.#{t}".add(1,2)
3

最后一种方法只是试探性的,其实你选择的方案应该是最优 Module.safe_concat,

如果你的需求真的可能输入一个从来没有exist的模块时,你应该使用Module.concat,但是你想一个方法去保证atom不会耗尽。

让我们最后来回顾一下Module最前面的@moduledoc

Provides functions to deal with modules during compilation time.

It allows a developer to dynamically add, delete and register attributes,
attach documentation and so forth. After a module is compiled, using many of the functions in this module will
raise errors, since it is out of their scope to inspect runtime data. Most of
the runtime data can be inspected via the __info__(attr) function attached to
each compiled module.

它本来就不是用来解决运行期间的问题的。。。。

[Elixir008]Nested Module里的动态函数调用方式的更多相关文章

  1. idapython实现动态函数调用批量注释

    部门小伙伴遇到一个样本需要对动态函数调用就行批量注释还原的问题,通过idapython可以大大的减少工作量,其实这一问题也是很多样本分析中最耗时间的一块,下面来看看如何解决这个问题(好吧这才是今年最后 ...

  2. (转)函数调用方式与extern "C"

    原文:http://patmusing.blog.163.com/blog/static/13583496020103233446784/ (VC编译器下) 1. CALLBACK,WINAPI和AF ...

  3. Android开发4: Notification编程基础、Broadcast的使用及其静态注册、动态注册方式

    前言 啦啦啦~(博主每次开篇都要卖个萌,大家是不是都厌倦了呢~) 本篇博文希望帮助大家掌握 Broadcast 编程基础,实现动态注册 Broadcast 和静态注册 Broadcast 的方式以及学 ...

  4. LoadRunner 脚本学习 -- 动态储存方式和静态储存方式

    我们在定义变量是,根据定义的位置不同,分为全局变量与局部变量.我出生在一个叫“舞阳”的小县城,在这个县城中也有人名“舞阳”,前一个作用于整个县城,后一个只作用于他个人.那么从变量值的存在生存期角度,又 ...

  5. JavaScript中七种函数调用方式及对应 this 的含义

    this 在 JavaScript 开发中占有相当重要的地位,不过很多人对this这个东西都感觉到琢磨不透.要真正理解JavaScript的函数机制,就非常有必要搞清楚this到底是怎么回事. 函数调 ...

  6. 函数调用方式--__thiscall调用方式和__cdecl,__stdcall有什么区别

    函数调用方式--__thiscall调用方式和__cdecl,__stdcall有什么区别 首先,__thiscall是关于类的一种调用方式,它与其他调用方式的最大区别是:    __thiscall ...

  7. C++动态存储方式与静态存储方式

    如果从变量值存在的时间(即生存期)来分,可将程序中的变量分为:动态存储方式和静态存储方式.它们所占用的存储空间区域不同. C++存储空间区域 代码区:存放可执行程序的程序代码.静态存储区:存放静态变量 ...

  8. 在<s:iterator>标签里给动态表格添加序号

    在<s:iterator>标签里给动态表格添加序号,需要用到<s:iterator>标签里的Status属性里的count eg:<s:iterator value=&q ...

  9. 函数调用方式__stdcall、__cdel

    函数调用方式关系对比如下: 关键字 调用规则 参数传递方向 返回 参数寄存器 堆栈的清除 __cdecl C语言 从右向左 EAX 无 调用者 __stdcall Win32标准  从右向左 EAX ...

随机推荐

  1. SeismicPro地震剖面显示程序

    SeismicPro是一个地震剖面显示软件,可从标准SEGY地震数据体中抽取纵测线和横测线的二维剖面,并以波形.变面积和变密度等多种方式进行专业化显示,可进行一键式显示方式切换,并可进行定制开发叠加井 ...

  2. 简易的可拖动的桌面悬浮窗效果Demo

    首先,我们需要知道,悬浮窗分为两种:Activity级别的悬浮窗,系统级别的悬浮窗 Activity级别的悬浮窗跟随所属Activity的生命周期而变化,而系统级别的悬浮窗则可以脱离Activity而 ...

  3. IOS 实现 AAC格式 录音 录音后自动播放

    废话不说了 不知道aac可以百度一下 下面直接上代码,一个h文件 一个m文件 搞定! #import <AVFoundation/AVFoundation.h> #import <U ...

  4. Swift的7大误区

    Swift正在完成一个惊人的壮举,它正在改变我们在苹果设备上编程的方式,引入了很多现代范例,例如:函数式编程和相比于OC这种纯面向对象语言更丰富的类型检查. Swift语言希望通过采用安全的编程模式去 ...

  5. Silverlight项目笔记8:层次布局、客户端读取shp、ExecuteCountAsync、柱状图、url传参

    1.层次布局 由于地图窗口和菜单栏都在一个父容器内,在浏览器缩小到一定程度点击地图弹出infoWindow时,会出现菜单栏遮挡infoWindow中间部分的现象,于是通过设置Canvas.ZIndex ...

  6. CoreAnimation-06-CAKeyframeAnimation

    概述 简介 CAKeyframeAnimation又称关键帧动画 CAKeyframeAnimation是抽象类CAPropertyAnimation的子类,可以直接使用 通过values与path两 ...

  7. strcpy

    /********************** *C语言标准库函数strcpy的一种典型的工业级的最简实现 *返回值:目标串的地址. *对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返 ...

  8. 为什么Erlang比C慢那么多倍?

    Erlang 一直以慢“著称”,本文就来看看 Erlang 慢在什么地方,为什么比实现同样功能的 C 语言程序慢那么多倍.Erlang 作为一种虚拟机解释的语言,慢是当然的.不过本文从细节上分析为什么 ...

  9. npm 配置全局文件

    nodejs.npm 按照默认安装完成即可. 1.设置一下全局目录:配置npm的全局模块的存放路径以及cache的路径,将以上两个文件夹放在NodeJS的主目录下,便在NodeJs下建立"n ...

  10. JSON实战案例--使用JSON进行数据交换实例

    内容: 1.访问javaScript对象的属性 2.访问Javacript对象数组 3.JSON字符串转换成JavaScript对象 4 .Java对象转换成JSON字符串 5 .使用JSON完成级联 ...