# \[feedback/help requested\] A practical introduction to kill-safe, concurrent programming in Racket

**URL:** <https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534>\
**Category:** Show & Tell\
**Created:** [November 25, 2023, 5:46am UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534 "2023-11-25T05:46:29Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![nikhilm](https://avatars.discourse-cdn.com/v4/letter/n/f08c70/32.png) [@nikhilm](https://racket.discourse.group/u/nikhilm)\
**Post date:** [November 25, 2023, 5:46am UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/1 "2023-11-25T05:46:29Z")

</div>

I’ve written a long tutorial exploring the user of Racket’s Concurrent ML (CML) inspired concurrency paradigm to write an API wrapping git-cat-file. It is meant to serve as an introduction to kill-safety and CML concurrency, while assuming some existing knowledge of Racket or other Schemes. I found that there weren’t a lot of resources beyond the reference documentation that explained how to put these APIs together, and I hope this can fill that hole.

Beyond any feedback about the writing itself, one request for help: Is there a way to make the links to Racket standard forms correctly link to [docs.racket-lang.org](http://docs.racket-lang.org), instead of being red squiggles? That would really increase the value of Scribble generating all those links. Thanks!

I'll post it to a wider audience soon.

[https://nikhilism.com/writing/racket-concurrency/](https://nikhilism.com/writing/racket-concurrency/)

---

<div class="post-metadata">

**Author:** ![EmEf](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@EmEf](https://racket.discourse.group/u/EmEf)\
**Post date:** [November 25, 2023, 1:11pm UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/2 "2023-11-25T13:11:24Z")

</div>

Assuming you use `(require (for-label racket))` etc, run scribble like this:

```scheme
scribble --htmls ++xref-in setup/xref load-collections-xref --dest $TARGET \
         --redirect-main "http://docs.plt-racket.org/" \
         cml-tutorial.scrbl 

```

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [November 25, 2023, 7:00pm UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/3 "2023-11-25T19:00:26Z")

</div>

- the match regexp pattern can be written with `or` using `and` to bind the match: `(and message (or "missing" "ambiguous"))`
- in the reader response, I’d probably do something like for/first + a rem function, though your single pass approach is reasonable:

```scheme
(define found
  (findf (lambda (p) (equal? got-key (Pending-key p))) pending))
(define new-pending
  (if found (remove found pending) pending))
(loop … (if found (cons (pending->response found contents) response-attempts) response-attempts) …)

```

The for/first would allow me to put pending-\>response in the loop, but then remove would be less concise (you’d need to remf and check for got-key again).

---

<div class="post-metadata">

**Author:** ![nikhilm](https://avatars.discourse-cdn.com/v4/letter/n/f08c70/32.png) [@nikhilm](https://racket.discourse.group/u/nikhilm)\
**Post date:** [November 25, 2023, 10:24pm UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/4 "2023-11-25T22:24:40Z")

</div>

Thanks for the tip! I found that using `+m` (when using Racket 8.9) instead of the xref stuff was enough. To get a single HTML file, my command was:

```scheme
raco scribble --html +m --redirect-main "https://docs.racket-lang.org/" --dest <path> --dest-name index.html scribblings/git-catter.scrbl

```

---

<div class="post-metadata">

**Author:** ![nikhilm](https://avatars.discourse-cdn.com/v4/letter/n/f08c70/32.png) [@nikhilm](https://racket.discourse.group/u/nikhilm)\
**Post date:** [November 25, 2023, 10:25pm UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/5 "2023-11-25T22:25:06Z")

</div>

Thank you for the `match` tip!  
For the filter, I will stick with my current approach.

---

<div class="post-metadata">

**Author:** ![yfzhe](https://avatars.discourse-cdn.com/v4/letter/y/f05b48/32.png) [@yfzhe](https://racket.discourse.group/u/yfzhe)\
**Post date:** [November 26, 2023, 6:12am UTC](https://racket.discourse.group/t/feedback-help-requested-a-practical-introduction-to-kill-safe-concurrent-programming-in-racket/2534/6 "2023-11-26T06:12:45Z")

</div>

For the `filter` question in section 5.2, i would use `for/fold`:

```scheme
(define-values (new-pending found)
  (for/fold ([new-pending '()]
             [found #f]
             #:result (values (reverse new-pending) found))
            ([p (in-list pending)])
    (cond
      [(and (not found) (equal? got-key (Pending-key p)))
       (values new-pending
               (pending->response p contents))]
      [else
       (values (cons p new-pending)
               found)])))

```
