POV-Ray : Newsgroups : povray.off-topic : More random humous : Re: More random humous Server Time
10 Oct 2024 03:18:48 EDT (-0400)
  Re: More random humous  
From: Invisible
Date: 8 Oct 2008 08:56:00
Message: <48ecade0$1@news.povray.org>
Warp wrote:

>   So basically if two completely different functions in completely separate
> parts of the program, both being called through long separate chains of
> function calls would require using the same RNG stream, you would have to
> put the seed parameter to each single function in both chains, even though
> most of the functions don't use the RNG for anything themselves.

Basically... yes.

Presumably it goes without saying that you try to avoid structuring your 
program that way.

>   If you add calling the RNG to some function in the future, and you want
> it to use the same RNG stream, you will then have to add the seed as a
> parameter to the function and modify all the lines where that function is
> called (which possibly requires to add the seed as parameter to those
> functions where those lines are, etc.) If you later remove the need for the
> RNG, then the parameter becomes obsolete, but are you going to remove it?

This kind of refactoring is both common and irritating. There are ways 
around it. For example, if you're doing a lot of work with random 
numbers, or any kind of state-carrying operation, you would probably use 
some kind of monad. That way, changing what gets passed around involves 
changing a few type signatures rather than wholesale editing of the 
whole program. (Especially if those type signatures are automatically 
derived, or even if you just use a few carefully chosen type aliases.)

>   How do you even create objects which have a state in Haskell?

Answer #1: You don't. You structure your program some other way.

Answer #2: If you really want to, Haskell does provide mutable storage.

> Suppose
> that you want to create, for example, sprite objects, each one with their
> own state. This state could be, for example, an image (which may be shared
> among several sprite objects, or different from other sprite objects, and
> which might even change in the future due to some event), their location
> on screen and a RNG stream specific to that sprite object. When you call
> some update function of the sprite, then the sprite could eg. call the RNG
> function using its own RNG stream, and update its own position on screen
> based on that. Given that you can't (in theory) assign anything to anything
> else, how can you make an object which changes its own state?

If the PRNG is unique to each sprite then it's fairly easy. You just 
write some function that takes a sprite structure describing how the 
sprite is right now (i.e., where it is, what image it has, etc.) and 
returns a new sprite structure.

More generally, for something like a complex game with collision 
detection, object interaction, user input from the outside world, etc., 
you would probably have some structure that represents the state of the 
entire "game world", and a function that computes a new state from the 
previous one plus some user input. You then have some functions that 
display this somehow.

>   I suppose I just can't stop thinking in the object-oriented way, where
> you have objects, each one having its own private state, each one being
> able to modify its own state without exposing the details to the outside.
> This feels like the ideal design for things like for example sprites, as
> described above. I just call, for example, some kind of update function
> of those sprites, and they do whatever; I don't know and I don't even
> want to know, from the outside, what they are doing inside.

Where this trips over is if, for example, how one object updates depends 
on the state of another object. Then you have to update them in the 
correct order - and *you* have to know what that order is. Otherwise 
some objects update themselves according to the old state of the world, 
and some according to the new state of the world, and others according 
to a hybrid state that should never actually exist.

If you take the entire game world and produce a new, modified copy of 
it, you know where you are, and you can compute things in any order. The 
only constraint is data dependencies - and the compiler will figure that 
out for you automatically; *you* do not need to care.

>   The Haskell way seems to be that you always have to somehow copy the
> elements from one place to another if you want to change them (which in
> itself already exposes some of the internal details of the object, as
> you need to be aware from the outside that the state of the object is
> changed, so you need to copy it somehow).

Not so much. You ask for the new version of some object, and it gives 
you an object of the appropriate type. Maybe this is a completely new 
object that was just constructed. Maybe it's actually the original 
object, unmodified. You can't tell, and you don't need to care. All that 
matters is that it's *potentially* a different object.

> But that seems to make it
> impossible to share an object (eg. an image) between several other
> objects (eg. sprites) if the state of that first object could be changed.
> How do you share a changing object among several other objects?

You cannot have object A point to object B, and alter object B such that 
object A sees the change. This is by design. You must duplicate object A 
and object B (thus making it clear that something has happened to *both* 
objects) for this to work.

That is, unless you actually use mutable state of course - which there 
is no law against. It just makes things like performing updates in the 
right order more tricky.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.