Best practice calling racket from rash?

I'm starting to use rash, and having a lot of fun. One question that I have is around best practices when invoking racket code. Specifically, as you might imagine, I have a bunch of shell scripts that invoke racket. When using Rash, I have the ability to make these "internal"; that is, my shell is in fact Racket, so I can just call this code directly. This makes me a bit nervous, in that I somehow feel as though the operating system's process abstraction is going to protect my shell-running racket even when my invoked-process racket goes belly-up... but maybe that's not really a problem in practice.

Does anyone have experience they can share?

Here's a simple blob of rash code formatted as a rashrc.rkt, replacing a ccs shell script that connects these two invocations of racket with &&, to show what I mean (and also to invite criticism; I suspect that I'm making a lot of simple things harder...)

#lang rash

(require shell/pipeline-macro
         (for-syntax racket syntax/parse))

(provide ccs)

(define (check-schedule)
        {raco make -v $HOME/scheduling/check-schedule.rkt}
        {racket $HOME/scheduling/check-schedule.rkt})

(define-pipeline-alias ccs
  (syntax-parser
    [(_) #'(=basic-object-pipe/form= check-schedule)]))
1 Like

Even though I love Racket, I can only use it from time to time. Back in the time, I saw Rash as a good oportunity to use Racket in my daily tasks.

I probably can't answer your question, but perhaps you can think of your Rash code not as isolated scripts, but rather as modules that you can reuse.

Finally, I fully understand you about having a lot of fun with the Racket / Rash pairing :smiling_face_with_tear::

(require racket/function
         racket/string
         racket/stream
         json
         qi )

(define (/ entry-name)
  (☯ (~> (hash-ref entry-name) (if list? sep _))))

(define (@ entry-name op entry-value)
  (☯ (pass (esc (λ (key) (op (hash-ref key entry-name) entry-value))))) )

(void (putenv "AWS_ACCESS_KEY_ID"     #{ echo $assumed-role | jq -r ".Credentials.AccessKeyId" }))
(void (putenv "AWS_SECRET_ACCESS_KEY" #{ echo $assumed-role | jq -r ".Credentials.SecretAccessKey" }))
(void (putenv "AWS_SESSION_TOKEN"     #{ echo $assumed-role | jq -r ".Credentials.SessionToken" }))

(let ([lambdas
       (for*/stream ([region (string-split regions)]
                     [result (in-list
                              (with-handlers ([exn:fail? (const '())])
                                #{ aws lambda list-functions \
                                       --region $region \
                                       |>> string->jsexpr \
                                       |> (☯ (~> (/ 'Functions)
                                                 (>< (/ 'FunctionArn))
                                                 ▽)) } ) ) ] )
         result) ])
  (if (stream-empty? lambdas)
      "no lambdas in any region"
      (~> (lambdas) stream-first display) ) )
2 Likes

Be careful with echo due to escape strings and special meanings; printf '%s\n' is more portable and won’t do strange things to its input.

2 Likes