【问题标题】:Does mutating arguments always introduce order dependent behaviour?变异参数是否总是引入顺序依赖行为?
【发布时间】:2018-07-01 05:05:18
【问题描述】:

我被告知突变会导致方法依赖于顺序(例如Mutation

但是,考虑到以下方法(为简单起见忽略 null),我看不出在给定相同参数的情况下,它们的行为会有什么不同。

void x(StringBuffer s) {
    s.append("a");
}

StringBuffer y(StringBuffer s) {
    return new StringBuffer(s.toString()).append("a");
}

所以我的问题是:

  1. 鉴于方法 x 会改变输入,是否存在与方法 x 相关的排序问题?
  2. x 可以被认为有副作用,但是,这实际上比方法 y 有什么缺点吗?比如 y 更容易并行化?

【问题讨论】:

    标签: java functional-programming mutation


    【解决方案1】:

    如果你在y 之后运行x,你会得到不同的输出,虽然y 的调用看起来是一样的。

    StringBuffer stringBuffer = new StringBuffer();
    x(stringBuffer);
    System.out.println(y(stringBuffer)); // gives aa
    
    StringBuffer stringBuffer = new StringBuffer();
    System.out.println(y(stringBuffer)); // gives a
    x(stringBuffer);
    

    在这个小例子中,stringBuffer 中实例的内部状态决定了输出,而调用哪个方法的详细信息对此很重要。

    x 有一个副作用,因为它改变了StringBuffer 实例的状态。这可能有几个优点和缺点,讨论这些超出了范围。

    PS:在 Java 中使用 StringBuilder 而不是 StringBuffer

    【讨论】:

    • 在没有突变的情况下不一样,即: int addOne(x) { return x + 1;即使在这里使用不同的 x 值调用此方法也会产生不同的结果,即使没有发生突变?
    • 不,不一样。您需要考虑提供的值相同的情况,因此不是不同的值x。如果这些输入相同,则顺序无关紧要,该函数将始终提供相同的结果。
    • StringBuffer 是一个可变对象的问题也是如此,这意味着即使传递了相同的值(即 ref),基础对象也可能具有不同的值,具体取决于其调用顺序?如果是这种情况,这对所有可变对象来说都不是问题——即使它们被传递给像 y 这样不会改变它的方法?
    • 它是可变的,它是变异的,这就是问题所在。 y 方法是“纯”的,不是问题的一部分,它只是显示效果。
    • 如果我们创建另一个像 y 这样的方法,你将 y 描述为纯的: StringBuffer z(StringBuffer s) { return new StringBuffer(s.toString()).append("b" ); } ...然后在 y 之后运行 z 仍然会给出不同的结果(而不是在 z 之后运行 y),即使两者都是 pure。因此,在这种情况下,使函数“纯”似乎并不一定能防止使用方法 x?
    猜你喜欢
    • 1970-01-01
    • 2013-07-30
    • 2014-10-30
    • 1970-01-01
    • 2017-09-01
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多