zoukankan      html  css  js  c++  java
  • [Erlang16]为什么要用MFA代替fun()–>end?

    MFA:Module Function Arguments.

    首先你要知道Module:Func(Args)和Func(Args)的区别在哪里?

    如果对细节感兴趣,可以通过这里了解:http://www.cnblogs.com/zhongwencool/p/erlang_hot_code.html

    总之:Erlang函数有local call和external call的区别,Local call 就是在函数在被定义的模块里面被调用,可以直接被调用: Func(Args); External call 就是显式的使用Module:Func(Args)来调用或import别的模块进来的调用.

    当同一个模块有2个版本被加载里,所有的local call都可以工作在当前版本状态,但是:external call只能调用到最新的版本!

    1.使用Fun的情景:

           1.1 先启动1个shell终端,分别名为test1:

    erl -name test1

           1.2 test1加载模块mfa_test.erl

    -module(mfa_fun).
    
    -export([cal/2,func/0]).
    
    cal(X,Y) ->
         X+Y.
    func() ->
           fun(X,Y) -> cal(X,Y) end.

    1.3在shell中输入:

    >Func = mfa_fun:func().
    #Fun<mfa_fun.1.52492151>
    >Func(1,2).
    3

    2.使用MFA的场景:

    改变mfa_test.erl中cal函数并重新加载这个模块:

    cal(X,Y) -> X*Y .

    1.5 再运行:

    >Func(1,2).
    3

    可以看到这个Func运行的local版本,如果把func改为以下版本:

    func() ->
           fun(X,Y) -> ?MODULE:cal(X,Y) end.

    那么结果是永远调用的最新版本代码,有兴趣可以自己验证下,你会感到好神奇,为什么Func变量是没有变化,但得到的结果却发生了变化。。。


    那么我们可以再进一步想一下:

    我们经常使用spawn(Func)来创建一个新的进程,如果我们永远不升级还好,如果热升级,会发生什么情况?

    这个local call的func,你怎么也改不了它,所以正常情况下最好使用:

    spawn(Mod,FuncName,Args)来创建进程,这样不会影响升级。

    再进一步,就是进程里面所有存local call都是无法被升级的,最佳实践就是一直用MFA就好!


    answer

         选择比努力重要,及时感恩,珍惜生活
  • 相关阅读:
    【shell脚本】批量修改扩展名===modifyExtension.sh
    【shell脚本】打印九九乘法表
    【shell脚本】显示进度条
    【Linux命令】Linux压缩及解压命令
    【Linux命令】ulimit设置最大文件打开数
    【mysql】修改mysql数据库密码
    【raid级别】RAID级别工作模式
    MyBatis之#{} and ${}
    MyBatis之foreach
    强制修改常量的值
  • 原文地址:https://www.cnblogs.com/zhongwencool/p/mfa_fun.html
Copyright © 2011-2022 走看看