
This code doesn’t do much, just four ‘ants’ doing random walks, but could anyone suggest ways this code could be better and more Racket in style.

#lang racket
(require 2htdp/universe 2htdp/image)
(struct ant (x y) #:transparent)
(define (random-walk value)
(+ value (sub1 (random 3))))
(define (move-ant in-ant)
(ant (random-walk (ant-x in-ant)) (random-walk (ant-y in-ant))))
(define (move-ants list-ants)
(map move-ant list-ants))
(define one-ant-list (list (ant 100 100) (ant 200 200) (ant 100 200) (ant 200 100)))
(define (render-world list-of-ants)
(let ((image (rectangle 400 400 "solid" "white")))
(map (λ (ant) (set! image (add-line image (ant-x ant) (ant-y ant) (add1 (ant-x ant)) (add1 (ant-y ant)) "black"))) list-of-ants)
image))
(big-bang one-ant-list
(on-tick move-ants)
(to-draw render-world))

@mark.warren to me, random-walk
could take both x and y coordinates. And the drawing with (set! image ...)
part could be render-ant

@jerome.martin.dev Good points, thanks.

apart from that, looks good :slightly_smiling_face:

maybe one style hint: inside a let
form, racketeers often use square brackets like so: (let ([x 4] [y 12] [z 28]) ...)

I find it easier to read let
, for
and other such constructs with square brackets

I don’t remember where but I stumbled upon someone saying it was great to differentiate between executed and not-executed forms.

@jerome.martin.dev Yes I forgot about the square bracket convention

oh also

the (set! image ...)
can be avoided completely

Cool

I didn’t like that

(define (render-world list-of-ants)
(for/fold ([image (rectangle 400 400 "solid" "white")])
([ant list-of-ants])
(add-line image
(ant-x ant)
(ant-y ant)
(add1 (ant-x ant))
(add1 (ant-y ant))
"black")))

Woo, like it.

for/fold
is a great construct in Racket :smile:

Yeah, still not got those for
constructs really sussed. I’m a Java programmer by day and to me for
means a whole other thing.

yep, it was the same for me first :stuck_out_tongue:

in fact, in standard scheme you would do something a bit similar using (let loop ([image (rectangle)]) (loop (add-line)))

but then when your familiar with the named let (it creates a function you can call to recurse), then for/fold
abstracts this for you

I love scheme

Personally, It took me multiple steps: 1) I don’t know Scheme 2) I don’t get it 3) Oh my god it’s awful 4) I love it

I’ve not changed the random walk function yet but this is looking better #lang racket
(require 2htdp/universe 2htdp/image)
(struct ant (x y) #:transparent)
(define (random-walk value)
(+ value (sub1 (random 3))))
(define (move-ant in-ant)
(ant (random-walk (ant-x in-ant)) (random-walk (ant-y in-ant))))
(define (move-ants list-ants)
(map move-ant list-ants))
(define one-ant-list (list (ant 100 100) (ant 200 200) (ant 100 200) (ant 200 100)))
(define (render-ant image ant)
(add-line image (ant-x ant) (ant-y ant) (add1 (ant-x ant)) (add1 (ant-y ant)) "black"))
(define (render-world list-of-ants)
(for/fold ([image (rectangle 400 400 "solid" "white")])
([ant list-of-ants])
(render-ant image ant)))
(big-bang one-ant-list
(on-tick move-ants)
(to-draw render-world))

definitely :smile:

Yep, I found once the parentheses thing went away in my head, it just feels such a natural way to do stuff.

Now I love them cause I just have to pass my cursor above them to see what the code structure is. I hated them and now I miss them in other languages x)

Hehe, know what you mean.

@jerome.martin.dev Many thanks, that feels slicker

you’re welcome :slightly_smiling_face:

Now to get the ants to take over the world.

:ant:

:grinning:

the for/x
variants in Racket are so much better than using map
, fold
, named lets or even plain recursive functions

I agree. Also, in some cases if you ever do need (or prefer) to use recursive functions? Using racket/match
to destructure lists can be much nicer than the traditional eye-glazing null?
car
cadr
cdr
soup.

@greg to me it’s still one of the biggest gains in using a ML like OCaml: destructuring pattern matching + Algebraic data types. though sometimes having all variants defined upfront gets in the way (there are polymorphic variants though)