Skip to content

Async/await #13

@weswigham

Description

@weswigham

C# started it, ES6 has it, even C++ 14 has it. Async/await is an amazingly simple construct for creating asynchronous code. Weather it's implemented with promises or continuations on the back end, we'll see later (likely continuations, since I see no indication that Brick will be event-loop based).

Regardless, the async/await keyword syntax for defining asynchronous code is a godsend; it helps create self-documenting code, simplifies asynchronous control flow, and fits snugly with already-defined chunks of brick syntax:

#=
A super-simple asynchronous IRC bot, to experiment with Brick
#=
import Net.Socket.TCP
server = "irc.freenode.org"
port = 6667
nick = "Brick"
channel = "#brick_bot"
commands = {
    "!quit": |sock:Socket, _:Array<String>| async {
        await sock.write("QUIT :Exiting")
        await sock.destroy!
        exit(0)
    },
    "!id": |sock:Socket, words:Array<String>| async -> boolean {
        await sock.write("PRIVMSG " + channel + " :" + words.implode(" "))
    }
}
async listener(sock:Socket, s:String)
    if s.substring(0, 6) == "PING :"
        await sock.write("PONG :" + s.substring(6, s.length))
    else
        let p = s.find(":")
            cs = s.substring(p, s.length)
            exp = cs.explode(" ")
        in
            if commands.has_key?(exp[0])
                puts(exp[0] + "> " + exp.drop(1).implode(" "))
                await commands.get(exp[0])(sock, exp.drop(1))
            else
                puts("> " + cs)
            end
        end
    end
end
async main
    let !sock = await TCP(server, port) in
        if not !sock.success?
            puts("Failed to connect to server")
        else
            await !sock.write("NICK " + nick)
            await !sock.write("USER " + nick + " 0 * :" + nick + " bot")
            await !sock.write("JOIN " + channel)
            sock.listen!(listener)
        end
    end
end

Important notes on what I see as proper use: async isn't an used like an access modifier like in C++ or C#, instead, it's an alternate keyword for function declaration, which implies that the return type should be wrapped in an Awaitable Promise/Future. This way, if manually specifying a type declaration for an async, you needn't include that yourself. In effect, the async keyword adds the type -> Awaitable<T> to the end of the type line. You'll notice that for lambdas, the async keyword appears after the argument types. If I specifying the lambda's return type, it would appears before that. This makes sense, since in practice, the keyword modifies the return type of the function.

As far as the specifics on how async/await interact with threading/blocking, the C# documentation section is excellent: http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_Threads

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions