ryansuchocki / microscheme

A Scheme subset for Atmel microcontrollers.

Home Page:http://ryansuchocki.github.io/microscheme/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Difference of behaviour when using map

YPares opened this issue · comments

commented

The following code works:

(define led1 (output 3))
(define led2 (output 13))

(define (loop)
  (toggle led1)
  (toggle led2)
  (pause 500))

(toggle led2)
(forever loop)

But if I replace loop by:

(define (loop)
  (map toggle (list led1 led2))
  (pause 500))

then it starts OK, and after 40 seconds, led1 just remains lit up and led2 blinks 4 times, misses a blink, blinks 4 times, etc.
It happens both on my Duemilanove and Nano (both with a 328p), same time before it acts weird, same behaviour. Does it work OK on the UNO?
(Using microscheme 0.9.3)

commented

I checked with for-each instead of map, it also start to behave weirdly after a time, but this time led1 just remains off.

commented

Ok, with

(define (loop)
  (for-each-vector toggle (vector led1 led2))
  (call-c-func "my_write" 70)
  (pause 500))

it flashes 6 times. It's on led2 which is on pin13 so I guess I'm getting NOT A PAIR/ OOB exceptions.
I plugged another led so as to leave pin13 only for exceptions, and yes it's definitely an OOB.

This is a known problem when you call lambda, cons, list or vector within any infinite or high-frequency loop.

Please read: http://microscheme.org/documentation#memman

In this example:

(define (loop)
  (map toggle (list led1 led2))
  (pause 500))

list is using some memory on every allocation of the loop, which is never recovered. 2 to 8 KB quickly runs out... The best solution is to do it like you said in the first snippet. Otherwise, you can free that memory manually like this:

(define (loop)
  (free! (map toggle (list led1 led2)))
  (pause 500))

In the second example, vector is causing the same problem. Again, you can either move the allocation out of the loop, or manually free the memory...

(define (loop)
  (free! (for-each-vector toggle (vector led1 led2)))
  (call-c-func "my_write" 70)
  (pause 500))
(let ((myleds (vector led1 led2)))
  (define (loop)
    (for-each-vector toggle myleds)
    (call-c-func "my_write" 70)
    (pause 500))

Sorry, I got that very last bit wrong. define must be top-level, so it has to be:

(define myleds (vector led1 led2))

(define (loop)
  (for-each-vector toggle myleds)
  (call-c-func "my_write" 70)
  (pause 500))
commented

Oh, ok thanks!
I shouldn't have skimmed over this part when reading the docs the first time. Great!