高度易变领域中的不可变的功能对象[英] Immutable functional objects in highly mutable domain

本文是小编为大家收集整理的关于高度易变领域中的不可变的功能对象的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我目前在Scala的业余时间学习功能编程,我有一个闲置的新手问题.

我可以看到在进行诸如计算haar小波变换之类的事情时拥有不变的对象的优雅 - 即,当对象表示的数据本身不会改变.

但是我看到了一个博客,有人在展示不变性时以小型游戏为例.如果一个生物对象收到损坏,则不会改变其状态 - 它返回了带有新的命中点的新生物对象和一个新的" aggro to x to x"标志.魔兽世界说,但是,如果我们要设计像MMORPG之类的东西.战场上的一百名玩家...可能有数千次攻击和抛光/减震咒语效果以不同的方式影响他们.是否仍然可以使用完全不可变的对象设计系统?对我来说,似乎每个" tick"会有大量的新实例.为了获得当前有效的对象实例,所有客户端都必须经常经过某种中央" gameworld"对象或?

功能性编程是否为此缩放,或者这是"最佳工具最佳工作,可能在这里不变"的情况?

推荐答案

对我来说,似乎每个" tick"都会有一群新实例.

的确,就是这样.我有一个haskell应用程序读取市场数据供稿(在六个小时的交易日内,大约有500万条消息,我们感兴趣的数据),并为各种事情保持"当前状态",例如最新的竞标并为乐器提供价格和数量,我们的模型适合市场等等.在剖析模式下,模拟该程序的运行是非常令人恐惧的,并观看其分配和GC接近288在运行的前500秒内,记忆(或接近我机器RAM的大小的50,000倍). (如果不进行分析,该图将大大较高,因为分析不仅会减慢应用程序的速度,而且还强迫所有这些都在一个核心上运行.)

但请记住,纯语言实现的垃圾收集器针对这种行为进行了优化.我对应用程序的总体速度非常满意,而且我认为这是相当苛刻的,因为我们必须从市场供稿中分析几百个消息,进行一些相当广泛的计算以构建我们的模型,并使用它模型生成订单以尽快进入交易所.

其他推荐答案

通常在功能编程中,您将不会具有C ++样式构造函数.然后,即使从概念上讲,您一直在创建对象,但这并不意味着编译器必须制作代码来分配新对象,因为它不能影响程序的行为.由于数据是不可变的,因此编译器可以看到您刚刚指定的值以及已传递到您的功能中的值.

然后,编译器 can 创建真正紧密的编译代码,该代码仅在需要时计算特定对象中的字段.这项工作的工作程度取决于您使用的编译器的质量.但是,干净的功能编程代码告诉编译器与类似程序的C编译器相比,有关代码的编译器要多得多,因此,一个好的编译器 May 生成的代码比您期望的更好.

因此,至少从理论上讲,没有理由关注.功能编程实现可以扩展以及面向对象的堆分配实现.实际上,您需要了解与您合作的语言实施的质量.

其他推荐答案

mmorpg是已经是不变性的示例.由于游戏是在服务器和游戏玩家系统中分发的,因此绝对没有一个中心的" GameWorld"对象.因此,任何通过电线发送的对象都是不可变的 - 因为接收器不会更改.相反,如果有一个新对象或消息作为响应发送.

我从来没有写过分布式游戏,所以我不知道它们是如何实施的,但是我怀疑对对象的更新是在本地计算的,要么是在电线上以差异为diff.

例如,您正在玩​​命令和征服.您的猛mm象坦克正处于准备好基地的准备模式下.您的对手使用轻型坦克探索您的基地.您的猛mm虫射击并击中对手的坦克,造成损坏.

这个游戏非常简单,因此我怀疑尽可能在本地计算很多很多.假设两个玩家的计算机最初是在游戏状态方面保持同步的.然后,您的对手会单击将其轻型坦克移至您的基地.一条消息(不可变)通过电线发送给您.由于要移动储罐的算法(可能是)确定性是确定性的,因此您的命令和征服副本可以在屏幕上移动对手的坦克,更新游戏状态(可能是不可变或可变的).当轻型坦克在您的猛mm栓坦克范围内时,您的坦克就会发射.在服务器上生成一个随机值(在这种情况下,任意选择一台计算机作为服务器),以确定射击是否击中对手.假设坦克受到打击,并且必须对对手的坦克进行更新,则只有差异 - 坦克的新装甲水平已降至22%,这一事实被发送到电线上,以同步两名球员的比赛.此消息是不可变的.

代表坦克的玩家计算机上的对象是无关紧要的还是无关紧要的;它可以两种方式实现.每个玩家都不会直接改变其他游戏玩家游戏的状态.

本文地址:https://www.itbaoku.cn/post/627400.html

问题描述

I'm currently learning functional programming in my spare time with Scala, and I have an idle newbie question.

I can see the elegance of having immutable objects when doing something like calculating a Haar wavelet transform - i.e. when the data itself being represented by the objects doesn't change.

But I saw a blog where someone had a small game as an example when demonstrating immutability. If a creature object recieved damage, it didn't change its state - it returned a new creature object with the new hitpoints and a new "aggro towards X" flag. But if we were to design something like a MMORPG, World of Warcraft say. A hundred players in a battleground... possibly thousands of attacks and buffing/debuffing spell effects affecting them in different ways. Is it still possible to design the system with completely immutable objects? To me it would seem like there would be a ginormous swarm of new instances each 'tick'. And to get the currently valid instance of objects, all clients would constantly have to go through some sort of central "gameworld" object, or?

Does functional programming scale for this, or is this a case of "best tool for best job, probably not immutable here"?

推荐答案

To me it would seem like there would be a ginormous swarm of new instances each 'tick'.

Indeed, that is the case. I have a Haskell application that reads a market data feed (about five million messages over the course of a six-hour trading day, for the data in which we're interested) and maintains "current state" for various things, such as the most recent bid and offer prices and quantities for the instruments, how well our model fits the market, etc. etc. It's rather frightening to simulate a run of this program against a recorded feed in profiling mode and watch it allocate and GC close to 288 TB of memory (or close to 50,000 times the size of my machine's RAM) in the first 500 seconds of its run. (The figure would be considerably higher without profiling, since profiling not only slows down the application, but also forces it all to run on one core, as well.)

But keep in mind, the garbage collector in pure language implementations is optimized for this sort of behavior. I'm quite happy with the overall speed of my application, and I think that it's fairly demanding, in that we have to parse several hundred messages per second from the market feed, do some fairly extensive calculations to build our model, and use that model to generate orders to go to the exchange as quickly as possible.

其他推荐答案

Typically in functional programming you won't have C++ style constructors. Then, even though conceptually you are creating objects all the time, it doesn't mean that the compiler has to make code to allocate a new object, because it can't affect the behaviour of the program. Since the data is immutable, the compiler can see what values you've just specified, and what has been passed into your functions.

Then, the compiler can create really tight compiled code that just calculates the fields in the specific objects when they are needed. How well this works depends on the quality of the compiler you use. However, clean functional programming code tells the compiler quite a lot more about your code than a C compiler for a similar program could assume, and so therefore a good compiler may generate better code than what you might expect.

So, at least in theory, there's no reason to be concerned; functional programming implementations can scale just as well as object oriented heap allocate implementations. In practice, you need to understand the quality of the language implementation you are working with.

其他推荐答案

An MMORPG is already an example of immutability. Since the game is distributed across servers and gamers' systems, there is absolutely not a central "gameworld" object. Thus, any object that gets sent over the wire is immutable — because it doesn't get changed by the receiver. Instead, a new object or message gets sent as a response, if there is one.

I've never written a distributed game so I don't know exactly how they're implemented, but I suspect that updates to objects are either computed locally or sent as diffs over the wire.

For example, you're playing Command & Conquer. Your mammoth tank is sitting in ready mode guarding your base. Your opponent approaches with a light tank to explore your base. Your mammoth tank shoots and hits your opponent's tank, causing damage.

This game is pretty simple, so I suspect a lot is computed locally whenever possible. Assume the two players' computers are initially in sync in terms of game state. Then your opponent clicks to move his light tank into your base. A message (immutable) is sent to you over the wire. Since the algorithm to move a tank is (probably) deterministic, your copy of Command & Conquer can move your opponent's tank on your screen, updating your game state (could be immutable or mutable). When the light tank comes in range of your mammoth tank, your tank fires. A random value is generated on the server (in this case, one computer is chosen arbitrarily as the server) to determine whether the shot hits your opponent or not. Assuming the tank was hit and an update to your opponent's tank must be made, only the diff — the fact that the tank's new armor level has decreased to 22% — is sent over the wire to sync the two players' games. This message is immutable.

Whether the object on either player's computer representing the tank is mutable or immutable is irrelevant; it can be implemented either way. Each player does not directly change the state of other gamers' game.