Up to Main Index                          Up to Journal for November, 2013

                   JOURNAL FOR THURSDAY 28TH NOVEMBER, 2013
______________________________________________________________________________

SUBJECT: Parsing state and method values
   DATE: Thu 28 Nov 22:03:51 GMT 2013

This week has been an incredibly stressful one and I thought I wasn't going to
get any time to work on WolfMUD. Exactly because it had been so stressful I
made sure to make the time and I'm glad I did as it proved to be particularly
productive.

When Go 1.1 was released it introduced method values. These are methods that
are bound to specific receiver values. For the parsers this allow the code to
be considerably simplified.

Below I've tried to come up with a simple yet relevant example. The example is
driven by the count in the state struct. In reality we would be driven by an
input source such as from the user or maybe scripted.


   1 package main
   2
   3 type state struct {
   4   count int
   5   next  func()
   6 }
   7
   8 func Init() *state {
   9   s := &state{}
  10   s.next = s.welcome
  11   return s
  12 }
  13
  14 func main() {
  15   for s := Init(); s.next != nil; s.next() {
  16   }
  17 }
  18
  19 func (s *state) welcome() {
  20   println("Welcome!")
  21   s.next = s.greet
  22 }
  23
  24 func (s *state) greet() {
  25   if s.count++; s.count < 4 {
  26     println("Hello...")
  27   } else {
  28     s.next = s.bye
  29   }
  30 }
  31
  32 func (s *state) bye() {
  33   println("Bye Bye :(")
  34   s.next = nil
  35 }


If you run it, the following output is produced:


  Welcome!
  Hello...
  Hello...
  Hello...
  Bye Bye :(


So what is going on here? We have a state struct which is used to pass around
our current data values. In this case count which is an int and next which is
a function that takes no parameters and returns nothing - actually it will
refer to a method receiver bound to the state struct instance called s.

The expression s.next = s.func where func is one of welcome, greet or bye will
create the method value and store it in s.next. We can then call whichever
method is stored in s.next by doing s.next().

So lines 15 and 16 become a very simple driver. We initialise our state struct
s and keep calling whatever method value is stored in s.next until s.next is
nil.

So in the example the processing is:


  Initially s.next is s.welcome
  s.welcome sets s.next to s.greet
  s.greet increments the count
  if count is less than 4 we don't change s.next so s.greet is called again
  when count is 4 or more we set s.next to s.bye
  s.bye sets s.next to nil terminating our driving for loop


Obviously for the actual parsers there is a lot more too it but that's
basically how they now work. As soon as I finish the coding off and do a lot a
cleanup I'll push the changes out for people to play with.

Incidentally by doing things this way I have a lot of cleanup to do as I'm
actually ripping out a lot of existing code that is no longer needed...

--
Diddymus


  Up to Main Index                          Up to Journal for November, 2013