+Even nonblocking I/O code is straightforward to write.
+Thanks to the "suspendable ports" code introduced in Guile 2.2,
+writing asynchronous, nonblocking networked code looks mostly
+like writing the same synchronous code.
+8sync's scheduler handles suspending and resuming networked
+code that would otherwise block.
+@item
+8sync aims to be "batteries included".
+Useful subsystems for IRC bots, HTTP servers, and so on are
+included out of the box.
+@item
+8sync prioritizes live hacking.
+If using an editor like Emacs with a nice mode like Geiser,
+an 8sync-using developer can change and fine-tune the behavior
+of code @emph{while it runs}.
+This makes both debugging and development much more natural,
+allowing the right designs to evolve under your fingertips.
+A productive hacker is a happy hacker, after all!
+@end itemize
+
+In the future, 8sync will also provide the ability to spawn and
+communicate with actors on different threads, processes, and machines,
+with most code running the same as if actors were running in the same
+execution environment.
+
+But as a caution, 8sync is still very young.
+The API is stabilizing, but not yet stable, and it is not yet well
+"battle-tested".
+Hacker beware!
+But, consider this as much an opportunity as a warning.
+8sync is in a state where there is much room for feedback and
+contributions.
+Your help wanted!
+
+And now, into the wild, beautiful frontier.
+Onward!
+
+@node Tutorial
+@chapter Tutorial
+
+@menu
+* A silly little IRC bot::
+* Writing our own actors::
+* Writing our own network-enabled actor::
+* An intermission on live hacking::
+@end menu
+
+\f
+
+@node A silly little IRC bot
+@section A silly little IRC bot
+
+IRC! Internet Relay Chat!
+The classic chat protocol of the Internet.
+And it turns out, one of the best places to learn about networked
+programming.@footnote{In the 1990s I remember stumbling into some funky IRC chat rooms and
+being astounded that people there had what they called "bots" hanging
+around.
+From then until now, I've always enjoyed encountering bots whose range
+of functionality has spanned from saying absurd things, to taking
+messages when their "owners" were offline, to reporting the weather,
+to logging meetings for participants.
+And it turns out, IRC bots are a great way to cut your teeth on
+networked programming; since IRC is a fairly simple line-delineated
+protocol, it's a great way to learn to interact with sockets.
+(My first IRC bot helped my team pick a place to go to lunch, previously
+a source of significant dispute!)
+At the time of writing, venture capital awash startups are trying to
+turn chatbots into "big business"@dots{} a strange (and perhaps absurd)
+thing given chat bots being a fairly mundane novelty amongst hackers
+and teenagers everywhere a few decades ago.}
+We ourselves are going to explore chat bots as a basis for getting our
+feet wet in 8sync.
+
+First of all, we're going to need to import some modules. Put this at
+the top of your file:
+
+@example
+(use-modules (8sync) ; 8sync's agenda and actors
+ (8sync systems irc) ; the irc bot subsystem
+ (oop goops) ; 8sync's actors use GOOPS
+ (ice-9 format) ; basic string formatting
+ (ice-9 match)) ; pattern matching
+@end example
+
+Now we need to add our bot. Initially, it won't do much.
+
+@example
+(define-class <my-irc-bot> (<irc-bot>))
+
+(define-method (handle-line (irc-bot <my-irc-bot>) message
+ speaker channel line emote?)
+ (if emote?
+ (format #t "~a emoted ~s in channel ~a\n"
+ speaker line channel)
+ (format #t "~a said ~s in channel ~a\n"
+ speaker line channel)))
+@end example
+
+We've just defined our own IRC bot!
+This is an 8sync actor.
+(8sync uses GOOPS to define actors.)
+We extended the handle-line generic method, so this is the code that
+will be called whenever the IRC bot "hears" anything.
+This method is itself an action handler, hence the second argument
+for @verb{~message~}, which we can ignore for now.
+Pleasantly, the message's argument body is passed in as the rest of
+the arguments.
+
+For now the code is pretty basic: it just outputs whatever it "hears"
+from a user in a channel to the current output port.
+Pretty boring!
+But it should help us make sure we have things working when we kick
+things off.
+
+Speaking of, even though we've defined our actor, it's not running
+yet. Time to fix that!
+
+@example
+(define* (run-bot #:key (username "examplebot")
+ (server "irc.freenode.net")
+ (channels '("##botchat")))
+ (define hive (make-hive))
+ (define irc-bot
+ (bootstrap-actor hive <my-irc-bot>
+ #:username username
+ #:server server
+ #:channels channels))
+ (run-hive hive '()))
+@end example
+
+Actors are connected to something called a "hive", which is a
+special kind of actor that runs and manages all the other actors.
+Actors can spawn other actors, but before we start the hive we use
+this special @verb{~bootstrap-actor~} method.
+It takes the hive as its first argument, the actor class as the second
+argument, and the rest are initialization arguments to the
+actor.
+@verb{~bootstrap-actor~} passes back not the actor itself (we don't
+get access to that usually) but the @strong{id} of the actor.
+(More on this later.)
+Finally we run the hive with run-hive and pass it a list of
+"bootstrapped" messages.
+Normally actors send messages to each other (and sometimes themselves),
+but we need to send a message or messages to start things or else
+nothing is going to happen.
+
+We can run it like:
+
+@example
+(run-bot #:username "some-bot-name") ; be creative!
+@end example
+
+Assuming all the tubes on the internet are properly connected, you
+should be able to join the "##botchat" channel on irc.freenode.net and
+see your bot join as well.
+Now, as you probably guessed, you can't really @emph{do} much yet.
+If you talk to the bot, it'll send messages to the terminal informing
+you as such, but it's hardly a chat bot if it's not chatting yet.
+
+So let's do the most boring (and annoying) thing possible.
+Let's get it to echo whatever we say back to us.
+Change handle-line to this:
+
+@example
+(define-method (handle-line (irc-bot <my-irc-bot>) message
+ speaker channel line emote?)
+ (<- (actor-id irc-bot) 'send-line channel
+ (format #f "Bawwwwk! ~a says: ~a" speaker line)))
+@end example
+
+This will do exactly what it looks like: repeat back whatever anyone
+says like an obnoxious parrot.
+Give it a try, but don't keep it running for too long@dots{} this
+bot is so annoying it's likely to get banned from whatever channel
+you put it in.
+
+This method handler does have the advantage of being simple though.
+It introduces a new concept simply@dots{} sending a message!
+Whenever you see "<-", you can think of that as saying "send this
+message".
+The arguments to "<-" are as follows: the actor sending the message,
+the id of the actor the message is being sent to, the "action" we
+want to invoke (a symbol), and the rest are arguments to the
+"action handler" which is in this case send-line (with itself takes
+two arguments: the channel our bot should send a message to, and
+the line we want it to spit out to the channel).@footnote{8sync's name for sending a message, "<-", comes from older,
+early lisp object oriented systems which were, as it turned out,
+inspired by the actor model!
+Eventually message passing was dropped in favor of something called
+"generic functions" or "generic methods"
+(you may observe we made use of such a thing in extending
+handle-line).
+Many lispers believe that there is no need for message passing
+with generic methods and some advanced functional techniques,
+but in a concurrent environment message passing becomes useful
+again, especially when the communicating objects / actors are not
+in the same address space.}
+
+Normally in the actor model, we don't have direct references to
+an actor, only an identifier.
+This is for two reasons: to quasi-enforce the "shared nothing"
+environment (actors absolutely control their own resources, and
+"all you can do is send a message" to request that they modify
+them) and because@dots{} well, you don't even know where that actor is!
+Actors can be anything, and anywhere.
+It's possible in 8sync to have an actor on a remote hive, which means
+the actor could be on a remote process or even remote machine, and
+in most cases message passing will look exactly the same.
+(There are some exceptions; it's possible for two actors on the same
+hive to "hand off" some special types of data that can't be serialized
+across processes or the network, eg a socket or a closure, perhaps even
+one with mutable state.
+This must be done with care, and the actors should be careful both
+to ensure that they are both local and that the actor handing things
+off no longer accesses that value to preserve the actor model.
+But this is an advanced topic, and we are getting ahead of ourselves.)
+We have to supply the id of the receiving actor, and usually we'd have
+only the identifier.
+But since in this case, since the actor we're sending this to is
+ourselves, we have to pass in our identifier, since the Hive won't
+deliver to anything other than an address.
+
+Astute readers may observe, since this is a case where we are just
+referencing our own object, couldn't we just call "sending a line"
+as a method of our own object without all the message passing?
+Indeed, we do have such a method, so we @emph{could} rewrite handle-line
+like so:
+
+@example
+(define-method (handle-line (irc-bot <my-irc-bot>) message
+ speaker channel line emote?)
+ (irc-bot-send-line irc-bot channel
+ (format #f "Bawwwwk! ~a says: ~a" speaker line)))
+@end example
+
+@dots{} but we want to get you comfortable and familiar with message
+passing, and we'll be making use of this same message passing shortly
+so that @emph{other} actors may participate in communicating with IRC
+through our IRC bot.
+
+Anyway, our current message handler is simply too annoying.
+What we would really like to do is have our bot respond to individual
+"commands" like this:
+
+@example
+<foo-user> examplebot: hi!
+<examplebot> Oh hi foo-user!
+<foo-user> examplebot: botsnack
+<examplebot> Yippie! *does a dance!*
+<foo-user> examplebot: echo I'm a very silly bot
+<examplebot> I'm a very silly bot
+@end example
+
+Whee, that looks like fun!
+To implement it, we're going to pull out Guile's pattern matcher.
+
+@example
+(define-method (handle-line (irc-bot <my-irc-bot>) message
+ speaker channel line emote?)
+ (define my-name (irc-bot-username irc-bot))
+ (define (looks-like-me? str)
+ (or (equal? str my-name)
+ (equal? str (string-concatenate (list my-name ":")))))
+ (match (string-split line #\space)
+ (((? looks-like-me? _) action action-args ...)
+ (match action
+ ;; The classic botsnack!
+ ("botsnack"
+ (<- (actor-id irc-bot) 'send-line channel
+ "Yippie! *does a dance!*"))
+ ;; Return greeting
+ ((or "hello" "hello!" "hello." "greetings" "greetings." "greetings!"
+ "hei" "hei." "hei!" "hi" "hi!")
+ (<- (actor-id irc-bot) 'send-line channel
+ (format #f "Oh hi ~a!" speaker)))
+ ("echo"
+ (<- (actor-id irc-bot) 'send-line channel
+ (string-join action-args " ")))
+
+ ;; ---> Add yours here <---
+
+ ;; Default
+ (_
+ (<- (actor-id irc-bot) 'send-line channel
+ "*stupid puppy look*"))))))
+@end example
+
+Parsing the pattern matcher syntax is left as an exercise for the
+reader.
+
+If you're getting the sense that we could make this a bit less wordy,
+you're right:
+
+@example
+(define-method (handle-line (irc-bot <my-irc-bot>) message
+ speaker channel line emote?)
+ (define my-name (irc-bot-username irc-bot))
+ (define (looks-like-me? str)
+ (or (equal? str my-name)
+ (equal? str (string-concatenate (list my-name ":")))))
+ (define (respond respond-line)
+ (<- (actor-id irc-bot) 'send-line channel
+ respond-line))
+ (match (string-split line #\space)
+ (((? looks-like-me? _) action action-args ...)
+ (match action
+ ;; The classic botsnack!
+ ("botsnack"
+ (respond "Yippie! *does a dance!*"))
+ ;; Return greeting
+ ((or "hello" "hello!" "hello." "greetings" "greetings." "greetings!"
+ "hei" "hei." "hei!" "hi" "hi." "hi!")
+ (respond (format #f "Oh hi ~a!" speaker)))
+ ("echo"
+ (respond (string-join action-args " ")))
+
+ ;; ---> Add yours here <---
+
+ ;; Default
+ (_
+ (respond "*stupid puppy look*"))))))
+@end example
+
+Okay, that looks pretty good!
+Now we have enough information to build an IRC bot that can do a lot
+of things.
+Take some time to experiment with extending the bot a bit before
+moving on to the next section!
+What cool commands can you add?
+
+\f
+@node Writing our own actors
+@section Writing our own actors
+
+Let's write the most basic, boring actor possible.
+How about an actor that start sleeping, and keeps sleeping?
+
+@example
+(use-modules (oop goops)
+ (8sync))
+
+(define-class <sleeper> (<actor>)
+ (actions #:allocation #:each-subclass
+ #:init-thunk (build-actions
+ (*init* sleeper-loop))))
+
+(define (sleeper-loop actor message)
+ (while (actor-alive? actor)
+ (display "Zzzzzzzz....\n")
+ ;; Sleep for one second
+ (8sleep (sleeper-sleep-secs actor))))
+
+(let* ((hive (make-hive))
+ (sleeper (bootstrap-actor hive <sleeper>)))
+ (run-hive hive '()))
+@end example
+
+We see some particular things in this example.
+One thing is that our @verb{~<sleeper>~} actor has an actions slot.
+This is used to look up what the "action handler" for a message is.
+We have to set the #:allocation to either @verb{~#:each-subclass~}
+and use @verb{~#:init-thunk~}.@footnote{@verb{~build-subclass~} returns
+a thunk to be called later so that each subclass may correctly build
+its own instance. This is important because the structure returned
+contains a cache, which may vary from subclass to subclass based on
+its inheritance structure.}
+
+The only action handler we've added is for @verb{~*init*~}, which is called
+implicitly when the actor first starts up.
+(This will be true whether we bootstrap the actor before the hive
+starts or create it during the hive's execution.)
+
+In our sleeper-loop we also see a call to "8sleep".
+"8sleep" is like Guile's "sleep" method, except it is non-blocking
+and will always yield to the scheduler.
+
+Our while loop also checks "actor-alive?" to see whether or not
+it is still registered.
+In general, if you keep a loop in your actor that regularly yields
+to the scheduler, you should check this.@footnote{Or rather, for now you should call @verb{~actor-alive?~} if your code
+is looping like this.
+In the future, after an actor dies, its coroutines will
+automatically be "canceled".}
+(An alternate way to handle it would be to not use a while loop at all
+but simply send a message to ourselves with "<-" to call the
+sleeper-loop handler again.
+If the actor was dead, the message simply would not be delivered and
+thus the loop would stop.)
+
+It turns out we could have written the class for the actor much more
+simply:
+
+@example
+;; You could do this instead of the define-class above.
+(define-actor <sleeper> (<actor>)
+ ((*init* sleeper-loop)))
+@end example
+
+This is sugar, and expands into exactly the same thing as the
+define-class above.
+The third argument is an argument list, the same as what's passed
+into build-actions.
+Everything after that is a slot.
+So for example, if we had added an optional slot to specify
+how many seconds to sleep, we could have done it like so:
+
+@example
+(define-actor <sleeper> (<actor>)
+ ((*init* sleeper-loop))
+ (sleep-secs #:init-value 1
+ #:getter sleeper-sleep-secs))
+@end example
+
+This actor is pretty lazy though.
+Time to get back to work!
+Let's build a worker / manager type system.
+
+@example
+(use-modules (8sync)
+ (oop goops))
+
+(define-actor <manager> (<actor>)
+ ((assign-task manager-assign-task))
+ (direct-report #:init-keyword #:direct-report
+ #:getter manager-direct-report))
+
+(define (manager-assign-task manager message difficulty)
+ "Delegate a task to our direct report"
+ (display "manager> Work on this task for me!\n")
+ (<- (manager-direct-report manager)
+ 'work-on-this difficulty))
+@end example
+
+This manager keeps track of a direct report and tells them to start
+working on a task@dots{} simple delegation.
+Nothing here is really new, but note that our friend "<-" (which means
+"send message") is back.
+There's one difference this time@dots{} the first time we saw "<-" was in
+the handle-line procedure of the irc-bot, and in that case we explicitly
+pulled the actor-id after the actor we were sending the message to
+(ourselves), which we aren't doing here.
+But that was an unusual case, because the actor was ourself.
+In this case, and in general, actors don't have direct references to
+other actors; instead, all they have is access to identifiers which
+reference other actors.
+
+@example
+(define-actor <worker> (<actor>)
+ ((work-on-this worker-work-on-this))
+ (task-left #:init-keyword #:task-left
+ #:accessor worker-task-left))
+
+(define (worker-work-on-this worker message difficulty)
+ "Work on one task until done."
+ (set! (worker-task-left worker) difficulty)
+ (display "worker> Whatever you say, boss!\n")
+ (while (and (actor-alive? worker)
+ (> (worker-task-left worker) 0))
+ (display "worker> *huff puff*\n")
+ (set! (worker-task-left worker)
+ (- (worker-task-left worker) 1))
+ (8sleep (/ 1 3))))
+@end example
+
+The worker also contains familiar code, but we now see that we can
+call 8sleep with non-integer real numbers.
+
+Looks like there's nothing left to do but run it.
+
+@example
+(let* ((hive (make-hive))
+ (worker (bootstrap-actor hive <worker>))
+ (manager (bootstrap-actor hive <manager>
+ #:direct-report worker)))
+ (run-hive hive (list (bootstrap-message hive manager 'assign-task 5))))
+@end example
+
+Unlike the @verb{~<sleeper>~}, our @verb{~<manager>~} doesn't have an implicit
+@verb{~*init*~} method, so we've bootstrapped the calling @verb{~assign-task~} action.
+
+@example
+manager> Work on this task for me!
+worker> Whatever you say, boss!
+worker> *huff puff*
+worker> *huff puff*
+worker> *huff puff*
+worker> *huff puff*
+worker> *huff puff*
+@end example
+
+"<-" pays no attention to what happens with the messages it has sent
+off.
+This is useful in many cases@dots{} we can blast off many messages and
+continue along without holding anything back.
+
+But sometimes we want to make sure that something completes before
+we do something else, or we want to send a message and get some sort
+of information back.
+Luckily 8sync comes with an answer to that with "<-wait", which will
+suspend the caller until the callee gives some sort of response, but
+which does not block the rest of the program from running.
+Let's try applying that to our own code by turning our manager
+into a micromanager.
+
+@example
+;;; Update this method
+(define (manager-assign-task manager message difficulty)
+ "Delegate a task to our direct report"
+ (display "manager> Work on this task for me!\n")
+ (<- (manager-direct-report manager)
+ 'work-on-this difficulty)
+
+ ;; Wait a moment, then call the micromanagement loop
+ (8sleep (/ 1 2))
+ (manager-micromanage-loop manager))
+
+;;; And add the following
+;;; (... Note: do not model actual employee management off this)
+(define (manager-micromanage-loop manager)
+ "Pester direct report until they're done with their task."
+ (display "manager> Are you done yet???\n")
+ (let ((worker-is-done
+ (mbody-val (<-wait (manager-direct-report manager)
+ 'done-yet?))))
+ (if worker-is-done
+ (begin (display "manager> Oh! I guess you can go home then.\n")
+ (<- (manager-direct-report manager) 'go-home))
+ (begin (display "manager> Harumph!\n")
+ (8sleep (/ 1 2))
+ (when (actor-alive? manager)
+ (manager-micromanage-loop manager))))))
+@end example
+
+We've appended a micromanagement loop here@dots{} but what's going on?
+"<-wait", as it sounds, waits for a reply, and returns a reply
+message.
+In this case there's a value in the body of the message we want,
+so we pull it out with mbody-val.
+(It's possible for a remote actor to return multiple values, in which
+case we'd want to use mbody-receive, but that's a bit more
+complicated.)
+
+Of course, we need to update our worker accordingly as well.
+
+@example
+;;; Update the worker to add the following new actions:
+(define-actor <worker> (<actor>)
+ ((work-on-this worker-work-on-this)
+ ;; Add these:
+ (done-yet? worker-done-yet?)
+ (go-home worker-go-home))
+ (task-left #:init-keyword #:task-left
+ #:accessor worker-task-left))
+
+;;; New procedures:
+(define (worker-done-yet? worker message)
+ "Reply with whether or not we're done yet."
+ (let ((am-i-done? (= (worker-task-left worker) 0)))
+ (if am-i-done?
+ (display "worker> Yes, I finished up!\n")
+ (display "worker> No... I'm still working on it...\n"))
+ (<-reply message am-i-done?)))
+
+(define (worker-go-home worker message)
+ "It's off of work for us!"
+ (display "worker> Whew! Free at last.\n")
+ (self-destruct worker))
+@end example
+
+(As you've probably guessed, you wouldn't normally call @verb{~display~}
+everywhere as we are in this program@dots{} that's just to make the
+examples more illustrative.)
+
+"<-reply" is what actually returns the information to the actor
+waiting on the reply.
+It takes as an argument the actor sending the message, the message
+it is in reply to, and the rest of the arguments are the "body" of
+the message.
+(If an actor handles a message that is being "waited on" but does not
+explicitly reply to it, an auto-reply with an empty body will be
+triggered so that the waiting actor is not left waiting around.)
+
+The last thing to note is the call to "self-destruct".
+This does what you might expect: it removes the actor from the hive.
+No new messages will be sent to it.
+Ka-poof!
+
+Running it is the same as before:
+
+@example
+(let* ((hive (make-hive))
+ (worker (bootstrap-actor hive <worker>))
+ (manager (bootstrap-actor hive <manager>
+ #:direct-report worker)))
+ (run-hive hive (list (bootstrap-message hive manager 'assign-task 5))))
+@end example
+
+But the output is a bit different: