Channel Directions in Scheme

In Scheme, we don’t have built-in channel functionality like in some other languages. However, we can simulate similar behavior using procedures and shared state. Here’s an example that demonstrates a similar concept:

; This `ping` procedure only accepts a procedure for sending
; values. It would be a runtime error to try to receive in this procedure.
(define (ping send-proc msg)
  (send-proc msg))

; The `pong` procedure accepts one procedure for receives
; (`receive-proc`) and a second for sends (`send-proc`).
(define (pong receive-proc send-proc)
  (let ((msg (receive-proc)))
    (send-proc msg)))

; Main procedure
(define (main)
  (let* ((pings '())
         (pongs '())
         (ping-send (lambda (msg) (set! pings (cons msg pings))))
         (ping-receive (lambda () (let ((msg (car pings)))
                                    (set! pings (cdr pings))
                                    msg)))
         (pong-send (lambda (msg) (set! pongs (cons msg pongs))))
         (pong-receive (lambda () (let ((msg (car pongs)))
                                    (set! pongs (cdr pongs))
                                    msg))))
    
    (ping ping-send "passed message")
    (pong ping-receive pong-send)
    (display (pong-receive))
    (newline)))

; Run the main procedure
(main)

In this Scheme version, we use procedures and shared state to simulate channel-like behavior:

  1. The ping procedure takes a send procedure and a message. It uses the send procedure to “send” the message.

  2. The pong procedure takes a receive procedure and a send procedure. It “receives” a message using the receive procedure and then “sends” it using the send procedure.

  3. In the main procedure, we set up lists pings and pongs to act as our “channels”. We define procedures to add to these lists (ping-send, pong-send) and to remove from them (ping-receive, pong-receive).

  4. We then use these procedures in a similar way to the original example, “sending” a message with ping, passing it through pong, and finally displaying the result.

When you run this program, it will output:

passed message

This example demonstrates how we can implement similar concepts in Scheme, even though it doesn’t have built-in channel functionality. The use of procedures to manipulate shared state provides a flexible way to implement various communication patterns between different parts of a program.