文不可无观点,观点不可无论据。

转载请注明出处

MATLAB功能强大,编程方便,是国际广泛使用的计算软件。目前已有很多书籍介绍其在工程上的应用,但很少有从程序设计语言的角度写的书或文章。

MATLAB准备写一个系列,50~100篇左右。内容是笔者的心得,追求市面的书上没有的,都是有小程序作为案例的。上一篇阅读量极少,有没有可能是内容较多,程序较多,让人烦躁?补充这篇算是补救吧,采用短文章风格。

MATLAB将变量存储在工作空间内(workspace),基工作空间(base workspace)保存MATLAB命令窗口或脚本中的变量。函数不使用基工作空间,每个函数有自己单独的工作空间,以实现数据的隔离保护。大多数情况下,MATLAB函数中的变量只能在函数中使用,而不能在其它函数和基工作空间使用,数据交互采用函数参数传递形式。

全局变量

global:global将变量申明为全局变量,注意的是,1)变量的申明必须在赋值前;2)全局变量在被引用前,需再次使用global声明。

persistent:persistent是一种特殊的全局变量,它仅对本很函数可见。运行下述函数多次,可发现其返回值每次递减。本命令类似于C语言下的static命令,值得注意的是,其初始化方法与C语言不同(static a=3;),而且此变量可以被clear functions命令(functions指具体的函数名)清除,除非在函数内增加mlock命令。

1   functionvariablescope

2   persistenta;

3   if(isempty(a)) a=3;end

4   a=a-1;

5   disp(a);

引用父(或基)工作空间

1   v = evalin('base', 'var');

其中evalin的第一个参数可以为’base’或’caller’,分别指基和父工作空间。

对基工作空间或父工作空间幅值

1   assignin('base', 'a', -1);

也可以使用:

1   evalin('base', 'a=-1;');

外部文件交换

采用外部文件交换可以跨越所有空间,在MATLAB内,save函数用于将本空间变量保存到文件中,load用于将变量导入本函数。

嵌套函数和匿名函数提供了一种称为闭包的能力。如下ode45的第一个参数为函数名,一般传入时间和自变量x,但有时需要传入更多的参数,这时可以使用λ函数(匿名函数)。

1   ode45(@(t, x, a) fun(t, x, a), tspan, x0, a)

值得注意的是,对于下述程序

其返回值均为3,这是因为b函数本身包括了被声明当时所处的环境,当外界环境改变时,它仍保留了当时的环境,这种保留当时环境的特性被称为闭包,它带来了一系列编程特性,将在讲函数型数据时详述。

MATLAB变量大部分表现与C语言相同,但其实现机制完全不同。C语言运行时,对变量的引用只表现为地址的指针的引用,其源程序中的名称已完全消失。在MATLAB中,当对变量赋值时,变量存在一个标签,从而也多出了更多的自省的机制。

直接运行whos命令,可以打印所有的变量。如下命令将工作空间内所有变量压缩到一个结构体内:

如下命令查看某个变量是否存在:exist('want_known', 'var');

如下命令查看函数中输入或输出参数有几个:nargin, nargout

如下命令传入函数的可变输入或输出参数:vargin, vargout

如下命令查看父函数名称:mfilename, dbstack

如下命令查看函数参数传入时的真实名称:inputname, dbstack

例如vargin, vargout可以这样使用

matlab不支持a=b=c=d=e=f=g=1的赋值,一个一个赋值太麻烦,这时可以采用逗号分隔符

deal函数代码如下

deal.m, MATLAB自带程序, edit deal即可看到

1   functionvarargout = deal(varargin)

2   ifnargin==1,

3     varargout = varargin(ones(1,nargout));

4       else

5         ifnargout ~= nargin

6           error('MATLAB:deal:narginNargoutMismatch',...

7                 'The number of outputs should match the number of inputs.')

8         end

9         varargout = varargin;

10       end

又如下述例子利用了跨域赋值和自省功能,可以在不返回值的情况下交换两输入参数。

1       functionexchangevar (a, b)

2       % 交换a、b变量的值

3       assignin('caller', inputname(1), b);

4       assignin('caller', inputname(2), a);

尽管MATLAB提供了更为丰富和方便的作用域控制功能,但编程序时并不建议使用。它使得函数逻辑复杂,程序更容易出错,调试更为困难,而且对于同一程序的同一形参,多次运行可能出现不同的返回值。在程序设计时常会追求一种引用透明性,即对同一程序同一形参的多次使用返回值均相同。这种理念引申出了一种不同于面向过程、面向对象的编程范式,称之为函数式编程,也将在后续介绍。函数式编程大家不一定要用,但学习后,对提高编程能力有所益处。

往期文章:

微信扫一扫

关注“理念世界的影子”

版权声明:

本文是"洞穴之外"作者原创文章,欢迎转载,须署名并注明来自“理念世界的影子”公众号。