摆脱朱莉娅的“警告:为不改变的字符串重新加工常量”?

时间:2016-06-16 11:08:54

标签: string warnings constants julia

在我的julia代码中,我使用了一些常量。其中一些常量是字符串(它们用作标识符)。我的问题是每当我运行julia脚本时,我总是会对常量字符串发出以下警告,即使我不更改常量WARNING: redefining constant pot_type

为了说明我的问题,这是一个MWE:

const pot_type = "constant"
const b = 12
println("Given parameters: Potential = $pot_type, b = $b .")

如果我两次运行此脚本,我将收到上述警告。 不仅如此,如果我只是在Julia控制台中输入const something = "somestring"两次,也会发生同样的事情。我得到WARNING: redefining constant something

我知道这不会以任何方式影响我的代码,但无论如何都要删除此警告或修复它?在我的实际代码中,每次我提交一些东西时它会创建5行,这个空间可以用来显示先前提交的输出。

编辑(让自己更清楚):问题是即使我没有重新定义常量,也会显示此WARNING消息,这意味着我给它赋予相同的值。而且,这个问题(据我所知)仅适用于String,而不适用于Int64Float64类型。例如:如果我写const b = 1.2然后const b = 1.4,我会收到预期的警告信息。现在,如果我写const b = 1.2然后const b = 1.2(相同的值),我将不再按预期收到警告。但是这不适用于字符串常量。即使在定义相同的值时,您也会收到警告。

3 个答案:

答案 0 :(得分:4)

如果你要使用某些东西作为常量,那么你真的不想多次定义它(毕竟,这是一个常数的点),当你多次运行你的脚本时,这正是你的意思是做。此外,重新定义常量并不会以任何方式影响您的代码并不是真的 - 在某些情况下它实际上会损害性能。再次,这就是你使用常量的原因 - 通过明确表示计算机不需要担心其值发生变化的特定对象来提高性能。

即使您为常量赋值相同的值,它仍然看起来像是对计算机的新赋值。即计算机不会,至少没有你更明确地告诉它(正如我在下面描述的那样)执行一些额外的逻辑来看“哦,我想这只是分配给它之前的常量的相同值,我想这可能没问题。“

一般情况下,在开发过程中会出现多次运行相同脚本的情况,我猜你正在做的事情。因此,作为对此的快速解决方法,您可以检查您的常量是否已定义,如果不是,则仅为其分配值。以下内容将实现:

isdefined(:b) || (const b = 12)

作为一个长期解决方案,一旦你超越了开发阶段(你一次又一次地运行相同的代码来解决bug),那么你真的想编写你的脚本以便它不会不能多次定义一个常数,否则,正如我所提到的那样,在这种情况下它并不是一个常量。

P.S。如果它有用,上面代码片段的解释如下。 ||运算符意味着Julia将评估第一个语句isdefined(:b),并且仅在第一个语句为(const b = 12)时才会进行评估。我们在第一个语句中使用:运算符来引用b的符号,即询问是否有任何分配给该符号b

答案 1 :(得分:4)

为了补充和详细说明@aireties的优秀答案,当您在同一模块中const x = a再次执行const x = b时,Julia目前有三种情况:

  1. 没有警告:如果a === b那么ab在程序上无法区分Henry Baker的EGAL [12]:用a替换b不会影响任何程序的行为,因此对常量x的重新定义是无操作,不需要警告。

  2. 警告:如果a !== btypeof(a) == typeof(b)则在当前版本的Julia中,生成的代码仍然有效,因为它仅取决于{{x的类型1}},保持不变,但程序的行为可能会受到x更改的影响,因为旧值a和新值b在编程上是可区分的。

  3. 错误:如果typeof(a) != typeof(b)重新分配x将使使用x的任何先前生成的代码的假设无效。因此,不允许进行此分配。

  4. ===谓词按类型和内容比较不可变值,因此1.5始终与1.5相同,因为无论您拥有多少“此实例”值,它们都不能变异,因此无法以任何方式区分。另一方面,值1.5(Float64)和Float32(1.5)是可区分的,因为它们具有不同的类型,即使它们代表完全相同的数值。但是,对于可变值,===谓词通过 identity 比较对象:除非它们是完全相同的对象,否则它们不被视为===。这是因为您可以通过编程方式区分两个可变值,即使它们以相同的值开始,也可以通过更改其中一个值并查看另一个值是否发生更改。

    在Julia中,字符串仅按约定不可变:String类型包装一个字节数组,这是可变的; String类型只是不暴露任何修改这些字节的函数。你仍然可以 - 在大多数程序中都不建议 - 进入并改变字符串的字节。这意味着相等字符串值的两个不同实例是不同的对象,因此彼此不===。因此,当您再次执行const x = "foo"及更晚const x = "foo"时,您将向!==分配两个不同的x字符串对象,以便您收到警告: / p>

    julia> const x = "foo"
    "foo"
    
    julia> const x = "foo"
    WARNING: redefining constant x
    "foo"
    

    另一方面,如果您将相同的字符串对象分配给x两次,则不会收到警告:

    ## in a new session ##
    
    julia> foo = "foo"
    "foo"
    
    julia> const x = foo
    "foo"
    
    julia> const x = foo
    "foo"
    

    将来,我们可能会更改String的实现,以便它实际上是不可变的,在这种情况下,使用相同类型的字符串值更新const绑定将不再产生警告,因为这两个值彼此为===

答案 2 :(得分:0)

正如 L.Grozinger 在评论中指出的那样,对 Michael Ohlrogge 的回答进行了快速更新。从 Julia v1.6 开始,格式应该是(对于给定的 const x = 10

(@isdefined x) || (const x = 10)