jdo*_*oig 8 functional-programming immutability
我正在尝试"学习更多"和"从函数式编程中吸取教训"以及不可变性对并发性有益的想法等.
作为一个思想练习,我想象一个简单的游戏,Mario-esq类型角色可以跑来跑去向他射击的敌人......
然后我试着想象这是使用不可变对象在功能上编写的.
这引发了一些困扰我的问题(成为一个势在必行的OO程序员).
1)如果我的小家伙在位置x10,y100向右移动1个单位,我只是使用他的旧值重新实例化他的x位置+1(例如x11,y100)?
2)(如果我的第一个假设是正确的)如果我的输入线程移动小家伙右1单位和我的敌人AI线程射击小家伙和敌人-ai线程解决输入线程然后我的家伙将失去健康,然后输入线程解决,获得它并向右移动......
这是否意味着我无法解雇 - 而且 - 即使在不变的情况下也会忘记我的线索?当我得到两个线程操作的结果时,我是否需要发送我的线程来执行他们的操作然后新的()同步的小家伙?还是有简单的"功能性"解决方案?
这与我日常所面临的线程问题略有不同.通常我必须决定我是否关心线程解决的顺序.在上述情况下,我在技术上并不关心他是否先受到伤害或移动.但我确实关心实例化期间的竞争条件会导致一个线程数据完全丢失.
3)(再次,如果我的第一个假设是正确的)不断实例化一个对象的新实例(例如马里奥家伙)有一个可怕的开销,使其成为一个非常严重/重要的设计决策?
编辑 对不起这个额外的编辑,我不是关于跟进问题的好习惯...
4)如果不变性是我应该努力的事情,甚至跳过实例化已经改变的对象的新版本的箍......如果我每次移动时实例化我的人(只有不同的位置)我不是如果他是可变的话我会遇到同样的问题吗?在某个时刻引用他的东西实际上是在看旧值吗?我越深入了解我的头脑越多,因为生成具有不同值的相同事物的新版本似乎是可变性的,通过黑客攻击.:¬?
我想我的问题是:这应该怎么做?如何改变他的立场有什么好处呢?
for(ever)//simplified game-loop update or "tick" method
{
if(Keyboard.IsDown(Key.Right)
guy = new Guy(guy){location = new Point(guy.Location.x +1, guy.Location.y)};
}
Run Code Online (Sandbox Code Playgroud)
令人困惑的是:上面的代码意味着那个人是可变的!(即使他的属性不是)
4.5)这完全是一成不变的人吗?
谢谢,
J.
- 如果我的小家伙在 x10,y100 位置向右移动 1 个单位,我是否只需使用他的旧值重新实例化他,并将他的 x 位置+1(例如 x11,y100)?
嗯,不一定。你可以实例化这个家伙一次,并在游戏过程中改变它的位置。您可以与代理一起对此进行建模。这家伙是代理,AI 也是,渲染线程也是,用户也是。
当人工智能射击该人时,它会向其发送一条消息,当用户按下箭头键时,它会发送另一条消息,等等。
let guyAgent (guy, position, health) =
let messages = receiveMessages()
let (newPosition, newHealth) = process(messages)
sendMessage(renderer, (guy, newPosition, newHealth))
guyAgent (guy, newPosition, newHealth)
Run Code Online (Sandbox Code Playgroud)
“一切”现在都是不可变的(实际上,在代理的双补丁队列的幕后可能确实有一些可变的状态)。
- 如果不变性是我应该努力追求的,甚至跳过实例化已更改的对象的新版本的麻烦……如果我在我的家伙每次移动时都实例化他(仅以不同的位置),我不是有完全相同的东西吗?如果他反复无常,我也会遇到问题吗?
嗯,是。使用可变值循环和使用不可变值重复是等效的。
编辑: