RiveScript in Go

Noah Petherbridge
kirsle
Posted by Noah Petherbridge on Tuesday, September 22 2015 @ 02:11:59 PM

Over the last couple months I've been slowly working on rewriting RiveScript in yet another programming language: Google's Go language! It's also my first project in Go, which is what tends to be the case (rewriting RiveScript in Java and Python were my first projects in those languages, too).

But this is the last time I'm going to be rewriting RiveScript from scratch.

With the recent release of Golang 1.5, a Go package can be compiled down to a C-compatible shared object file (like a .so or .dll, though I think they're still working on the DLL part). It means that modules written in Go can be linked from other programming languages, especially C or C++, but also to any programming language that can be extended with C. Which, as it turns out, is most of them.

For example, if I want to make RiveScript available to Ruby programmers, I can theoretically create a binding in Ruby for the Go version of RiveScript rather than rewrite RiveScript in Ruby.

The first language I'll probably do this to is Python, because I found a blog about writing Python modules in Go which will be pretty helpful. There's already a native RiveScript module for Python, but it will be a nice learning experience anyway. And who knows, it might even outperform the native Python version. ;)

Back to RiveScript-Go, a feature I think is interesting is that it natively supports JavaScript object macros via a library called otto, which implements a JavaScript interpreter natively in Go. The default rivescript.exe with my Go module already builds in the support for JavaScript objects. :)

Example implementation of the Go module:

package main

import (
    "bufio"
    "fmt"
    "strings"
    rivescript "github.com/aichaos/rivescript-go"
    "github.com/aichaos/rivescript-go/lang/rivescript_js"
)

func main() {
    // Initialize the bot.
    bot := rivescript.New()

    // JavaScript object macro handler.
    jsHandler := rivescript_js.New(bot)
    bot.SetHandler("javascript", jsHandler)

    // Golang functions work too, but must be compiled in.
    bot.SetSubroutine("gotest", func(rs *rivescript.RiveScript, args []string) string {
        return "Hello from Go!"
    })

    // Load a directory of RiveScript files.
    bot.LoadDirectory("./brain")

    bot.SortReplies()

    // Drop into the interactive command shell.
    reader := bufio.NewReader(os.Stdin)
    for {
        fmt.Print("You> ")
        text, _ := reader.ReadString('\n')
        text = strings.TrimSpace(text)
        if len(text) == 0 {
            continue
        }

        reply := bot.Reply("localuser", text)
        fmt.Printf("Bot> %s\n", reply)
    }
}

The JavaScript objects also get full access to the RiveScript object, so they can call methods like CurrentUser() and SetUservar().

Check it out on GitHub: https://github.com/aichaos/rivescript-go

Also, if I ever write a successor to RiveScript, I'll probably only implement it in Go or some other portable language rather than rewrite it five different times in five different languages. Rewriting something is a good way to learn a new language, but then it becomes pretty tedious maintaining them all. ;)

Categories:

[ Blog ]

Comments

There are 0 comments on this page.

Add a Comment

Your name:
Your Email:
Message:
Comments can be formatted with Markdown, and you can use
emoticons in your comment.

If you can see this, don't touch the following fields.



Kirsle
Channels
Creativity
Software
Web Tools
Subdomains
Miscellany
Links


Fan Club