The project I am working on defines some complex structures that receive messages and run within their own thread. The structures are user-defined and transformed via macros to threads and runtime stuff. Roughly speaking we can say that a complex structure consists of some behaviour that implements the logic, and a procedure for spawning an instance of the behaviour. In the code below I have vastly simplified the situation, where a behaviour defined by the create-thread-behaviour
macro is a simple thunk that can be spawned via the spawn
macro. I'd like to implement the ability for (an instance of) a behaviour to send messages to itself via a self
parameter that would be bound to (current-thread)
(~ the thread that is running the behaviour).
I've tried to rig something up using syntax-parameterize
but for some reason cannot get it to work. The code below implements a simple application that should clarify what I want to achieve - the special point of interest is the (unimplemented) <self>
reference towards the bottom.
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (create-thread-behaviour stx)
(syntax-parse stx
[(_ body:expr ...+)
#'(λ () body ...)]))
(define-syntax (spawn stx)
(syntax-parse stx
[(_ behaviour:id)
#'(thread behaviour)]))
(define behaviour
(create-thread-behaviour
(let loop ()
(define message (thread-receive))
(printf "message: ~a~n" message)
(thread-send <self> "And this is crazy.")
(loop))))
(define instance (spawn behaviour))
(thread-send instance "Hey I just met you")
So the thing with syntax parameters that I tried is the following, which raises the self-defined "can only be used in a behaviour" error. I know I have correctly used syntax parameters before, but perhaps I have just been looking at the problem for too long.
(require racket/stxparam)
(define-syntax-parameter self
(lambda (stx) (raise-syntax-error (syntax-e stx) "can only be used in a behaviour")))
(define-syntax (spawn stx)
(syntax-parse stx
[(_ behaviour:id)
#'(thread
(lambda ()
(syntax-parameterize ([self #'(current-thread)])
(behaviour))))]))
syntax-parameterize
? That’s definitely the right tool for the job here, and it would probably be more helpful to point out what you’re missing than to reimplement all of it. – Bron