网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
08月20日漏签0天
mathematica吧 关注:19,856贴子:73,993
  • 看贴

  • 图片

  • 吧主推荐

  • 游戏

  • 20回复贴,共1页
<<返回mathematica吧
>0< 加载中...

为什么b=a; f[a_]:=b; f[2]不输出2?——说说显式存在的重要性

  • 只看楼主
  • 收藏

  • 回复
  • xzcyr
  • 吧主
    15
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
为方便修订,文章放在了云笔记上,请大家多点一下鼠标。有什么意见或建议欢迎提出:
http://note.youdao.com/noteshare?id=a9c14381c11b44ad47980c44c200d529


  • 青衣瓦屋
  • 小吧主
    12
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
很多细节以前没注意,学习了!
一点小问题,代码2 /. 1 -> a中1前面的空格可能上传时被吃掉了,建议加上括号以免歧义。


2025-08-20 19:07:40
广告
不感兴趣
开通SVIP免广告
  • guocong89
  • For循环
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
个人认为该说法欠妥
单就title提到的问题, 并不是显式存在的问题, 应该是SetDelayed执行机制问题
我们先看一下Set功能Possible Issues第一条描述:
In the presence of global variables, pattern variables may show unexpected behavior

继续看tutorial/ImmediateAndDelayedDefinitions
开宗明义说了:
You may have noticed that there are two different ways to make assignments in the Wolfram Language: lhs=rhs and lhs:=rhs. The basic difference between these forms is when the expression rhs is evaluated. lhs=rhs is an immediate assignment, in which rhs is evaluated at the time when the assignment is made. lhs:=rhs, on the other hand, is a delayed assignment, in which rhs is not evaluated when the assignment is made, but is instead evaluated each time the value of lhs is requested.
Set是定义时计算, SetDelayed是使用时计算
那么我们来看看这两个的本质区别
就拿title问题举例
b = a;
f[a_] := b
f[2]
这个结果是 a
d = c;
g[c_] = d
g[2]
这个结果是 2
没错, 这对新人来说特别具有迷惑性
但是如果你弄懂了上面的本质区别, 就会知道
g[c_]=d => g[c_]=c
??g 也会看到相同的结论
因此在执行g[2]时, 相当于执行了With[{c=2}, c], 注意, 这里的c是临时变量, 并不是对全局变量c进行赋值
同样的, 执行 f[2], 相当于执行了 With[{a=2}, b]
这里的a依然是临时变量a, 并不是b等于的那个a, 所以b的值依然是a, 不是2
综上所述, 理解这个问题最根本的是明白Mathematica里面Pattern的变量不是实际的变量, 而是占位符的名字罢了
如果系统接受过编程训练, 那就是实参和形参的区别, 至于是Pass By Value还是Pass By Reference, 甚至更细分的 Pass By Reference Call By Value那就不是本帖讨论的范畴了, 具体可以参考维基百科, https://en.wikipedia.org/wiki/Pass_by_reference


  • guocong89
  • For循环
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
如果非要说是"显式存在", 那当然是没问题, 因为Pattern的执行就是显式匹配, 不是值匹配, 这么理解当然没问题
但我觉得强行往显式存在上靠是不合理的, 因为绝大部分语言在处理参数时都是按照名字去匹配的, 也就是所谓的显式存在.
比如来段c代码
#include <stdio.h>
int a;
int b;
void f(int a)
{
printf("%d\n", b);
}
int main(void)
{
a = 10;
b = a;
f(5);
return 0;
}
虽然概念上稍微有些不同, 但我觉得原理是一致的
外面我们定义了b=a=10
传参我们让a=5
但为什么输出的时候b=10而不是5呢?
明明b=a啊
因为参数a并不是外部的a, 两者是完全没有关系的变量
同样的, f[a_]:=b
a就是一个参数名, 和外面定义的b=a完全没有关系, 这点是承认了吧
所以就是一个编程语言里最最普通的实参形参的问题, 没必要去和显式存在联系起来
至于DownValue, HoldFirst, HoldAll的问题, 那只是一个计算优先级的问题而已, 无非是影响了
f[a_]:=XXXX(b) 是否优先计算XXXX(b)而已, 虽然我觉得整个Hold系统设计的很糟糕, 要不然也不会新开发出Active系统了
如果优先计算了XXXX(b), 那就变成了 f[a_]->a
没有优先计算, 那就是 f[a_]->b
仅此而已


  • guocong89
  • For循环
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
或者来点可能更暴力的解释, 虽然不太严谨
情况1:
a=10
f[a_]:=a
f[5]
这里三个a分别命名为 a1, a2, a3
不论是用显式存在理论还是参数作用域理论
a2<=>a3, a2和a1没有任何关系
因此, 当我们把a2用5替代时, a3=5, 于是输出了5
情况2:
a=10
b=a
f[a_]:=b
f[5]
这里依然是 a1, a2, a3
同时有 b1, b2
显然 a1<=>a2, a3和a1没有任何关系
因为b2没有在f参数表里出现, 所以不会被localize, 依然是全局的b1, 所以b2<=>b1
那么执行f[5]时, a3被5替代
但是a1=a2=10
b2=b1=a2
所以输出10就一目了然了


  • guocong89
  • For循环
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
不上c++的代码, 这里就和Mathematica的b=a等价了
#include <iostream>
using namespace std;
int a = 10;
int &b = a;
void f(int a)
{
cout<<b<<endl;
}
int main()
{
a = 20;
f(5);
return 0;
}


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 20回复贴,共1页
<<返回mathematica吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示