在学习有关 Scala 的一些教程时,我想到了这个问题,但我认为一般来说,在函数式编程方面很有趣。
我不确定 FP 中不变性的重要性。我可以想到两种不同的情况:
1) 类方法不返回实际字段,而是返回它们的副本。例如,如果我们有一个需要保持不可变的类 Dog,那么它的功能:
getToys() { return new ArrayList(this.toys); }
Run Code Online (Sandbox Code Playgroud)
代替:
getToys() { return this.toys; }
Run Code Online (Sandbox Code Playgroud)
这种情况对我来说很有意义,在第二种情况下,客户端代码实际上可能会损坏对象。我的怀疑在于第二种情况:
2) 在 Scala 和大多数其他 FP 语言中,我们更喜欢递归调用:
sum(x: List[Int], acc: Int) {
if(x.isEmpty) return acc;
sum(x.tail, acc + x.head);
}
Run Code Online (Sandbox Code Playgroud)
与传统的 for 循环递增累加器相反。原因是这个累加器是一个可变变量。
那个变量永远不会暴露在函数之外,所以为什么要让它不可变呢?
编辑:
似乎最重要的最佳实践是引用透明性而不是严格的不变性,这意味着我们不关心可变状态,只要它不能被客户端代码发现。然而,人们仍然声称,即使可变状态影响局部变量(如我的第一个示例),代码也更具可读性或更易于推理。
就个人而言,我认为循环比递归更具可读性。
所以真正的问题是:为什么使用不可变变量的代码更容易阅读/推理?
我正在编写一个 redux reducer 来从状态对象中删除一个键:
state = {
items: {
key1: {foo: 'bar'},
key2: {foo: 'baz'}
},
someOtherKey: 'value'
}
Run Code Online (Sandbox Code Playgroud)
我的减速机:
function reducer(state, action) {
if (action=='DEL') {
return {
...state,
items: {
...state.items,
[action.key]: undefined
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我预计这将返回一个删除了相应属性的新状态,但它返回一个新状态,其中键仍然存在于对象中,但值为undefined。
ES6 中是否有一种优雅的方式来编写这样的 reducer?我想我可以使用Object.assign和删除属性,但上面的模式更具表现力,所以如果可能的话,我想这样写。
我想用另一个元素替换数组中的特定元素,如下所示:
let replace = ["123","87","123","765","som","123","op","123"].map {$0 == "123" ? $0 = "replace" : $0}
Run Code Online (Sandbox Code Playgroud)
但我不能这样做,因为编译器会抛出我的错误:
error: cannot assign to value: '$0' is immutable
Run Code Online (Sandbox Code Playgroud)
那么,这可能会改变0美元变得可变吗?
在下面的代码中,我发现如果我们在参数中传递map,使用putAll方法可能会导致问题
public class Main {
public static void main(String...strings ) {
Etudiant e1=new Etudiant(5, "A");
Etudiant e2=new Etudiant(6, "B");
Map<Integer, Etudiant> map= new HashMap<>();
map.put(1, e1);
map.put(2, e2);
Map<Integer, Etudiant> map2= new HashMap<>();
map2.put(1,map.get(1));
map2.put(1,map.get(2));
changeMe(map2);
System.out.println(map.get(1));
Map<Integer, Etudiant> map3= new HashMap<>();
map3.putAll(map);
changeMe(map3);
System.out.println(map.get(1));
}
private static void changeMe(Map<Integer, Etudiant> etudiants) {
etudiants.get(1).name="K";
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是输出结果:
Etudiant [age=5, name=A]
Etudiant [age=5, name=K]
Run Code Online (Sandbox Code Playgroud)
你能解释一下这个区别吗?
为什么使用putAll之后对象会发生变化?
我想从原子转换为字符串。
Input = 'hello world'.
Output = "hello world".
Run Code Online (Sandbox Code Playgroud)
我如何实现这一目标?
我有一个包含 Arraylist 的类ArrayList<Move> moves。我从另一个类调用该 Arraylist 的 getter 并添加一个 move: panel.getMoves().add(move)。但是当我之后遍历 Arraylist 时,发生了一些非常奇怪的错误,暗示没有正确添加移动。
我必须打电话panel.setMoves(panel.getMoves().add(move))吗?如果是这样,为什么我一直认为列表是可变的?
据我对Javascript的正确理解,我们有两种不同的传递方式:按值传递和按引用传递。按值表示传递字符串或数字的时间。通过引用传递对象或数组时。
上次在某个项目中,我注意到反模式->有人为 this.props.arrayOfNames = newArrayOfNames;
我还没有机会进行测试,但是...它会以某种方式改变父母的对象吗?引用?
我有一个方法,需要以一年(int)作为参数。根据传入的年份,我需要分配一个变量,然后在查询中使用该变量:
def findByYear (year: Int): Future[Int] = {
val tableName = ""
year match {
case 1970 => tableName = "table1970" //this errors out
case 1980 => tableName = "table1980" //this errors out
}
config.db.run {
sqlu"SELECT count(*) from #${tableName}"
}
}
Run Code Online (Sandbox Code Playgroud)
由于scala不允许重新分配,因此出现了以上错误。有没有更好的方法来执行此操作,而不是将config.db.run子句放在每个子句中,case后者将成为非常重复的代码?
我有清单说-
List("aa","1","bb","2","cc","3","dd","4")
如何列出具有偶数和奇数位置的元组:
(aa,1),(bb,2),(cc,3),(dd,4)
immutability ×10
scala ×3
collections ×2
java ×2
arraylist ×1
core ×1
erlang ×1
javascript ×1
mutability ×1
python ×1
react-props ×1
reactjs ×1
redux ×1
string ×1
swift ×1