Channel Directions in Clojure

In Clojure, we can specify the direction of a channel when it’s used as a function parameter. This increases the type safety of the program.

(ns channel-directions
  (:require [clojure.core.async :as async :refer [>! <! >!! <!! go chan buffer close!]]))

;; This `ping` function only accepts a channel for sending
;; values. It would be a compile-time error to try to
;; receive on this channel.
(defn ping [pings msg]
  (>!! pings msg))

;; The `pong` function accepts one channel for receives
;; (`pings`) and a second for sends (`pongs`).
(defn pong [pings pongs]
  (let [msg (<!! pings)]
    (>!! pongs msg)))

(defn -main []
  (let [pings (chan 1)
        pongs (chan 1)]
    (ping pings "passed message")
    (pong pings pongs)
    (println (<!! pongs))))

To run the program:

$ lein run
passed message

In this Clojure version, we’re using the core.async library to work with channels. The >!! and <!! functions are used for putting values onto channels and taking values from channels, respectively, in a blocking manner.

The ping function takes a channel and a message, and puts the message onto the channel. The pong function takes two channels, receives a message from the first channel, and puts it onto the second channel.

In the -main function, we create two channels with a buffer size of 1, send a message through them using our ping and pong functions, and then print the result.

Note that Clojure’s core.async doesn’t have built-in support for specifying channel direction in function signatures. However, the intent can be conveyed through function documentation and careful usage.