Julia

时间:2018-09-23 10:50:16

标签: julia

有人知道茱莉亚为何选择无法修改作为输入给出的参数的功能设计的原因吗?无论如何,这都需要通过以荒谬的单元素表的形式表示这些数据来经历一个非常人为的过程。

具有相同局限性的

Ada在2012年的重新设计中放弃了它,获得了用户的极大满意。一个小的关键字(例如Ada中的关键字)很可能表明需要在输出端保留对参数的修改。

2 个答案:

答案 0 :(得分:2)

根据我在Julia中的经验,了解值和绑定之间的区别很有用。

Julia中的每个值在内存中都有一个具体的类型和位置。价值可以是可变的或不变的。特别是,当您定义自己的复合类型时,可以决定该类型的对象是可变的(mutable struct)还是不可变的(struct)。

当然,Julia具有内置类型,其中一些是可变的(例如数组),而其他则是不可变的(例如数字,字符串)。当然,它们之间存在设计权衡。在我看来,不变值的两个主要优点是:

  1. 如果编译器使用不可变的值,则它可以执行许多优化以加速代码;
  2. 用户可以肯定,将不可变项传递给函数不会改变它,并且这种封装可以简化代码分析。

但是,特别是,如果要将不可变值包装在可变包装器中,一种标准方法是使用Ref,如下所示:

julia> x = Ref(1)
Base.RefValue{Int64}(1)

julia> x[]
1

julia> x[] = 10
10

julia> x
Base.RefValue{Int64}(10)

julia> x[]
10

您可以将这些值传递给函数并在内部对其进行修改。当然Ref引入了不同的类型,因此方法的实现必须有所不同。

变量

变量是绑定到值的名称。通常,除了某些特殊情况,例如:

  1. 重新绑定模块A中模块B的变量;
  2. 重新定义一些常量,例如尝试用非函数值重新分配函数名称;
  3. 将具有指定类型的允许值的变量与无法转换为该类型的值重新绑定;

您可以重新绑定变量以指向所需的任何值。在大多数情况下,重新绑定是使用=或某些特殊构造(例如,在forletcatch语句中执行的)。

现在-切入点-函数将传递一个值,而不是绑定值。您可以修改函数参数的绑定(换句话说:您可以重新绑定参数指向的值),但是此参数是一个新鲜变量,其作用域位于函数内部。

例如,如果我们要打这样的电话:

x = 10
f(x)

更改变量x的绑定是不可能的,因为f甚至都不知道x的存在。它只会通过其值。特别是-正如我在上文中提到的-添加这样的功能将破坏规则,即模块A无法重新绑定模块B 中的变量,因为f可能是这样。在与定义x的模块不同的模块中定义。

该做什么

实际上,根据我的经验,使用此功能很容易:

  1. 通常,我只是从我分配给变量的函数中返回一个值。在Julia中,由于元组解包语法(例如。 x,y,z = f(x,y,z),其中可以定义f,例如为f(x,y,z) = 2x,3y,4z
  2. 您可以使用在代码执行之前已扩展的宏,因此可以有效地修改变量的绑定,例如macro plusone(x) return esc(:($x = $x+1)) end并且现在写y=100; @plusone(y)将更改y的绑定;
  3. 最后,您可以使用如上所述的Ref(或任何其他可变包装器-如您在问题中所指出的那样)。

答案 1 :(得分:0)

“有人知道茱莉亚为何选择无法修改作为输入给出的参数的功能设计的原因吗?” Schemer询问

您的问题是错误的,因为您假设错误的事情。

  1. 参数是变量

当您将事物传递给函数时,这些事物通常是值而不是变量。

例如:

function double(x::Int64)
  2 * x
end

现在使用调用它会发生什么情况

double(4)

修改参数x的功能的意义是什么,毫无意义。此外,该函数不知道如何调用它。

此外, Julia旨在提高速度。

修改参数的函数将难以优化,因为它会引起副作用。副作用是过程/函数在其范围之外更改对象/事物时。

如果函数未修改属于其调用参数的变量,那么您可以放心知道。

  1. 变量不会更改其值
  2. 函数的结果可以优化为常数
  3. 不调用该函数不会破坏程序的行为

以上三个因素导致功能语言快速运行和非功能语言缓慢运行。

此外,当您进入并行编程或多线程编程时,如果您(程序员)不了解该变量,则绝对不要更改其值。

“如何用建议的宏实现函数F(x),该函数返回布尔值并通过c:= c + 1修改c。F可用于以下Ada代码:c:= 0; While F(c)Loop ... End Loop;“ Schemer询问

我会写

function F(x)
  boolean_result = perform_some_logic()
  return (boolean_result,x+1)
end

flag = true
c = 0
(flag,c) = F(c)
while flag
  do_stuff()
  (flag,c) = F(c)
end

“不幸的是,没有,因为,我应该说,当F返回值False时,c必须再次取值0(随着Loop的生存,c会增加,并且在它死时返回0)。”

那我要写

function F(x)
  boolean_result = perform_some_logic()
  if boolean_result == true
      return (true,x+1)
  else
      return (false,0)
  end
end

flag = true
c = 0
(flag,c) = F(c)
while flag
  do_stuff()
  (flag,c) = F(c)
end