tomhrr / dale

Lisp-flavoured C
BSD 3-Clause "New" or "Revised" License
1.03k stars 48 forks source link

I tried to use Iterators for my Array, now it doesn't work as expected. #88

Closed porky11 closed 8 years ago

porky11 commented 8 years ago

https://github.com/porky11/planets/blob/iterator-test/src/game.dt#L145

tomhrr commented 8 years ago

On Sat, Sep 10, 2016 at 05:42:43AM -0700, Fabio Krapohl wrote:

https://github.com/porky11/planets/blob/iterator-test/src/game.dt#L145

From the branch:

(idle-func (void)
  (let ((e \ (end world)))
    (for (b \ (begin world)) (< b e) (setv b (successor b))
      (let ((planet (p (UniquePtr Planet)) (source b)))
        (incf ($ (@:@ (@ planet) pos) 0) (@$ (@:@ (@ planet) vel) 0))
        (incf ($ (@:@ (@ planet) pos) 1) (@$ (@:@ (@ planet) vel) 1)))))
  (glutPostRedisplay)
  (return))

'(@:@ (@ planet) pos)' expands internally to '(@ (: (@ (@ planet)) pos))'. The inner '(@ planet)' evaluates to a '(UniquePtr Planet)'. The subsequent dereference of that value (i.e. '(@ (@ planet))') copies the Planet value from the UniquePtr, so the addition operations are happening against a value that is effectively transient.

Something like the following will work:

(idle-func (void)
  (let ((e \ (end world)))
    (for (b \ (begin world)) (< b e) (setv b (successor b))
      (let ((planet (p Planet) (get (@ (source b)))))
        (incf ($ (@:@ planet pos) 0) (@$ (@:@ planet vel) 0))
        (incf ($ (@:@ planet pos) 1) (@$ (@:@ planet vel) 1)))))
  (glutPostRedisplay)
  (return))

The main difference being the use of 'get', which returns the pointer to the memory that the UniquePtr manages, rather than copying the underlying value.