mark.warren
2018-8-29 13:35:04

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.


mark.warren
2018-8-29 13:35:12

#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))


jerome.martin.dev
2018-8-29 13:57:01

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


mark.warren
2018-8-29 13:57:47

@jerome.martin.dev Good points, thanks.


jerome.martin.dev
2018-8-29 13:58:21

apart from that, looks good :slightly_smiling_face:


jerome.martin.dev
2018-8-29 13:59:47

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


jerome.martin.dev
2018-8-29 14:00:29

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


jerome.martin.dev
2018-8-29 14:01:41

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


mark.warren
2018-8-29 14:02:06

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


jerome.martin.dev
2018-8-29 14:04:58

oh also


jerome.martin.dev
2018-8-29 14:05:17

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


mark.warren
2018-8-29 14:06:37

Cool


mark.warren
2018-8-29 14:06:45

I didn’t like that


jerome.martin.dev
2018-8-29 14:07:38
(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")))

mark.warren
2018-8-29 14:09:11

Woo, like it.


jerome.martin.dev
2018-8-29 14:09:39

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


mark.warren
2018-8-29 14:11:43

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.


jerome.martin.dev
2018-8-29 14:11:59

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


jerome.martin.dev
2018-8-29 14:13:15

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


jerome.martin.dev
2018-8-29 14:13:57

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


mark.warren
2018-8-29 14:14:31

I love scheme


jerome.martin.dev
2018-8-29 14:16:53

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


mark.warren
2018-8-29 14:17:09

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))


jerome.martin.dev
2018-8-29 14:17:30

definitely :smile:


mark.warren
2018-8-29 14:18:40

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


jerome.martin.dev
2018-8-29 14:19:34

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)


mark.warren
2018-8-29 14:20:05

Hehe, know what you mean.


mark.warren
2018-8-29 14:22:22

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


jerome.martin.dev
2018-8-29 14:22:59

you’re welcome :slightly_smiling_face:


mark.warren
2018-8-29 14:24:14

Now to get the ants to take over the world.


jerome.martin.dev
2018-8-29 14:35:32

:ant:


mark.warren
2018-8-29 14:36:44

:grinning:


andreiformiga
2018-8-29 18:07:25

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


greg
2018-8-29 23:36:00

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.


andreiformiga
2018-8-30 00:52:01

@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)