Channel Directions in Swift

In Swift, we can specify the direction of data flow for function parameters that are channels. This increases the type safety of the program.

import Foundation

// This `ping` function only accepts a channel for sending
// values. It would be a compile-time error to try to
// receive on this channel.
func ping(pings: SendChannel<String>, msg: String) {
    pings.send(msg)
}

// The `pong` function accepts one channel for receives
// (`pings`) and a second for sends (`pongs`).
func pong(pings: ReceiveChannel<String>, pongs: SendChannel<String>) {
    if let msg = try? pings.receive() {
        pongs.send(msg)
    }
}

// In Swift, we need to create a custom Channel class to mimic Go's channels
class Channel<T> {
    private var buffer: [T] = []
    private let semaphore = DispatchSemaphore(value: 0)
    
    func send(_ element: T) {
        buffer.append(element)
        semaphore.signal()
    }
    
    func receive() throws -> T {
        semaphore.wait()
        return buffer.removeFirst()
    }
}

// SendChannel and ReceiveChannel protocols to enforce direction
protocol SendChannel<T> {
    func send(_ element: T)
}

protocol ReceiveChannel<T> {
    func receive() throws -> T
}

extension Channel: SendChannel, ReceiveChannel {}

// Main function equivalent
func main() {
    let pings = Channel<String>()
    let pongs = Channel<String>()
    
    ping(pings: pings, msg: "passed message")
    pong(pings: pings, pongs: pongs)
    
    if let result = try? pongs.receive() {
        print(result)
    }
}

main()

To run this program, save it as ChannelDirections.swift and use the Swift compiler:

$ swift ChannelDirections.swift
passed message

In this Swift version, we’ve created a custom Channel class to mimic Go’s channels, along with SendChannel and ReceiveChannel protocols to enforce direction. The ping and pong functions use these protocols to ensure type safety.

Note that Swift doesn’t have built-in channel support like Go, so this implementation is a simplified version to demonstrate the concept. In real-world applications, you might use Grand Central Dispatch (GCD) or other concurrency primitives for more robust asynchronous communication.