
What is the enlightenment I'm supposed to attain after studying finite automata? - johndcook
http://cstheory.stackexchange.com/questions/14811/what-is-the-enlightenment-im-supposed-to-attain-after-studying-finite-automata
======
chimeracoder
I was dreading taking Computer Science Theory for my undergraduate degree.
Turing machines bored me when I studied them in my introductory class, and I
saw the class as a necessary evil - a core requirement as well as a
prerequisite for my compilers class.

Boy, was I wrong. Despite what I'd anticipated, that class ended up being the
single most useful CS class that I took. I had the fortune of taking the class
with Alfred Aho[1] - I can't imagine a person more qualified to teach a class
on computation via automata; he literally _thinks_ in automata.

One day, I mentioned how I'd solved a particular programming problem (not for
class) by reasoning about it as if it were a pushdown automaton, and how I was
surprised that these techniques were still relevant, even for problems far
more high-level than, say, writing egrep. He told me, 'Sometimes when I have a
tough problem, I like to think of it as a language recognition problem, and it
becomes easier to solve.'

My brain may not be quite as oriented towards state machines as Prof. Aho's
is, but that trick has saved me countless times. Like functional programming,
it takes a bit of practice to wrap your head around it if you're not used to
it, but it can present really elegant solutions to problems that seem daunting
at first glance.

[1]<http://en.wikipedia.org/wiki/Alfred_Aho>

~~~
jacquesm
Consider me extremely jealous that you are studying under Prof. Aho, he's one
of the greats.

Statemachines are an incredibly useful tool. I've spent the better part of
last year untangling a huge pile of code and the solution in the end was to
split it all up into statemachines that communicate with each other using
simple synchronous messages.

That and that alone made the problem tractable. (Tractable to me, that is,
quite possibly some genius would be able to solve it in many different ways,
but this to me only underscores the value of statemachines as a tool).

~~~
charlieflowers
Would love to get your recommendations for good reading on state machines,
please. Getting curation from a someone who understands them well and uses
them in practice often would be fantastic.

~~~
jacquesm
Hm, I never thought there would be anybody interested in this stuff so it's
all over the place.

Basically what I've done is to model state machines using a bunch of C macros,
added a simple event system to drive the state transitions (receipt of message
translates into an event) which allows you to run any number of statemachines
in parallel inside a single C thread.

The events are prioritized to make sure that urgent stuff gets processed first
(such as statemachines terminating).

Imagine turning a very large bowl of spaghetti into a neatly ticking Swiss
watch :)

The particular element that made this a powerful tool was the fact that
statemachines (unlike function calls) are restrictive, the state-to-state
transitions are all known up front and any state changes that are not
explicitly allowed are forbidden. This simplifies design and debugging. An
extra benefit of doing it this way is that to run the resulting code on a
cluster requires only one (relatively, see 'fallacies of distributed
computing') simple addition, a way to pass messages between statemachines on
different nodes.

The end result of all this is that what was an absolutely gargantuan knot of
hard to read code became almost trivial by comparison, each statemachine is so
simple that the business logic portion is usually less than a page of code or
so (with a few exceptions), and all of the boilerplate is abstracted out and
taken care of by the macros.

Statemachines are small enough that they can be tested with ease and can then
be glued together using instantiation from within other statemachines.

The main loop of the program reads input and as soon as it has a complete
message will instantiate a statemachine to process it and will then send that
statemachine the message to set the ball rolling.

I'll see if I can find the time to describe the method in a bit more detail,
statemachines communicating using messages is a powerful metaphor for many
programming problems and I think it comes into its own when you're making
really complicated systems that have to be very predictable and reliable.

Note that even though there are some parallels with threads threads are simply
multiple paths of execution running in parallel through the same body of code,
statemachines are different in that instead of functions calling other
functions statemachines operate on a single chunk of data (called the state)
and will note the changes to the state by transiting to a new state. Every
program you write is in essence a statemachine but you normally don't make the
states explicit, instead you embody the (single) state that you've got in the
combination of program counter, stack and data memory. That makes the state
rather hard to untangle at any given moment.

Using statemachines explicitly breaks up this giant state vector into smaller
ones that operate on much simpler pieces of data using a series of permitted
operations, the outcome of which is rigidly defined.

I hope this all makes sense (it's 6:15 am and I haven't slept yet...)

~~~
bstpierre
It sounds like we've had similar experiences. I converted a handful of ad hoc
"state machines" in a telephony system to FA. The original code was loaded
with exceptions and special cases (and bugs). Converting to FA required
detailed analysis of the existing system to extract the distinct events and
states. I used a tool I wrote [1] to generate C state tables and an event loop
from a description of the states+events.

While the state machines that came out of the analysis were a big improvement,
they still weren't perfect. We came across a few bugs later on. Using a strict
representation of the state machines was a huge advantage in debugging and
maintenance. When everything is moving through the same event loop, it's easy
to add logging in the form "[timestamp] state A: event X -> state B". Adding a
new state or event to the machine (to fix a bug or add a new feature) is much
easier when everything is in one place.

In a couple of cases, the state machine started to become large and unwieldy.
Usually the cause was that there would be a couple of "meta" states: we'd have
states A, B, and C, but then we'd need to represent "states B and C when X is
true; states A and B when Y is true". Pulling X and Y into a separate machine
simplified the parent state machine -- every X and Y moved into the child
divides the number of states in the parent by as much as half. Then the parent
can inject events into the child, and the child can fire events back to the
parent.

[1] <http://bstpierre.org/Projects/smc/>

~~~
jacquesm
Indeed, it _really_ sounds like a very similar experience, up to and including
the code generation.

One more thing I ended up adding (that isn't on your list above) is a true
string type to the 'C' language (backwards compatible, works with pre-defined
strings as well), including garbage collection. I found that in order to get
the right level of abstraction the C string type was simply inadequate, it
kept forcing things into the foreground that should not even be visible at
that level.

The one thing still missing is copy-on-write for string duplication, but
that's a pretty tricky thing to implement in a thread safe and portable way.
This would give a huge performance boost, but at the moment that would be just
another case of premature optimization.

------
mcmatterson
Honestly, my answer to this came about many years after living through a very
theoretical CS undergrad, by way of a chapter in Charles Petzold's book,
'Code' (of all things. I originally bought the book for my dad to help him
understand 'what it was I did all day'). Basically, the insight centered
around the physicality of how FA are taught; FA are usually taught by thinking
of the FA itself as being fixed in space, and the tape as moving through it. I
always found that this lead to me thinking of the FA as a mechanical entity,
driven by some sort of magical tape; a useful thought exercise to be sure, but
not something that had many direct impacts on modern computing (outside of the
obvious regular language avenues). If you instead envision a FA as being a
flying head that moves back and forward across a tape that is fixed in space,
the ideas behind modern CPUs become much more clear: the tape is memory, the
FA is a CPU being stepped through successive states, and the 'location' of the
FA is the PC register. It's a seemingly small difference of conception, but
one that finally brought together two worlds for me that had evolved largely
distinctly before then.

It's tough to give justice to this insight, except to say that it really
helped crystalize the jump between the theoretical side of CS (which had
always been clear to me, if never terribly 'real'), and the applied side of CS
(which had always seemed to have evolved in some sort of semi-influenced
paralel universe to theory).

I don't know that it's the enlightenment you're looking for, but it's the one
that eventually found me.

~~~
eternalban
> If you instead envision a FA as being a flying head that moves back and
> forward across a tape that is fixed in space, the ideas behind modern CPUs
> become much more clear: the tape is memory, the FA is a CPU being stepped
> through successive states, and the 'location' of the FA is the PC register.

It would seem an apt analogy for the (basic) Von Neumann architecture, but
"modern" CPUs have a hierarchy of "cache lines" that quite neatly -- at least
in my mind -- map to a FA "fixed in space" [the cache line], with a "magical
tape" [virtual memory and cache coherence].

~~~
jacquesm
The key insight is that they're essentially the same thing.

------
btilly
Apparently if you understand finite automata, you'll be more enlightened than
Stack Overflow moderators.

My bitter example for this is
[http://stackoverflow.com/questions/11314077/algorithm-for-
ex...](http://stackoverflow.com/questions/11314077/algorithm-for-exclusion-of-
numbers/11317787) which question was deleted by moderators, then undeleted by
HN members. See [http://meta.stackoverflow.com/questions/138678/can-we-
please...](http://meta.stackoverflow.com/questions/138678/can-we-please-
reopen-this-programming-question) for the discussion on meta about the
question, and <http://news.ycombinator.com/item?id=4203350> for the HN
discussion at the time.

Incidentally the answer to that question provides a concrete example of
something you can easily do if you understand finite automata, that you
couldn't do without it, and that knowing how to use pre-built interfaces with
finite automata behind them (like regular expressions) would not help you
solve.

~~~
krichman
I find there's no point in participating in SO beyond a certain level of
ability. If you ask a truly difficult question, the odds of getting an answer
from someone who knows what they are talking about is not very good.
Meanwhile, any sort of discussion question gets closed.

The remainder is basic to intermediate questions that get answered with "this
is a duplicate of X".

~~~
joe_the_user
Yes,

It seems like both Wikipedia and Stack Overflow are done, at least
approximately. It is just that Wikipedia has at least some structures that
have adapted to being done while it seem that SO framework never considered
the possibility of the "frontier of general questions" being settled.

~~~
makomk
Wikipedia hasn't adapted as well to being "done" as you might think. For
instance, there's apparently at least one editor who just goes around
Wikipedia deleting random sections from articles that appear to be uncited. He
never adds anything, any contributions come from actual subject area experts
who have to take time away from editing other articles to deal with the mess
he leaves behind. The Wikipedia bureaucracy seems to think he's doing a great
job though! And this is just something I stumbled across a couple of days ago
by accident without following Wikipedia behind-the-scenes stuff; from what
I've heard they have problems with favouring policy wonks over content
contributers everywhere.

~~~
krichman
Those two websites are case studies of the Peter Principle.

------
DeepDuh
The concepts themselves have helped me a lot when programming parsers /
interpreters / compilers. Recently I've developed a language extension for
Fortran 90 along with a parser/analyzer in python that extracts structural
information of the the program as well as the additional directives. Solved it
in <1000 lines of python by combining an FA like structure (state switch using
a dictionary function lookup with a state variable inside a loop) with regular
expressions for the individual lines / state transitions. Sure, you could come
up with this on your own quite easily, but FA give you some powerful concepts
- even just knowing the keywords to google for can save you days of work.

The gist: When it comes to computer science and mathematical concepts, don't
ask why to study it, just study it - possible applications will probably come
at some point later in your career.

------
ctdonath
When you understand a subject well enough, the true basics become fascinating.
Without the full round trip from introduction to complexity to revealed
simplicity, the basics are nigh unto incomprehensible - yet giving new
students an intro thereto at least shows them where they are going. Quantum
mechanics is simple, but baffling to beginners; give them a taste and the
"aha" moment will come in time.

A = {0|1,...}

A[x] = !(A[y]•A[z])

That's all there is to computing, near as I've been able to simplify it.
Cellular automata may do a better job.

~~~
derleth
> Quantum mechanics is simple, but baffling to beginners

Quantum mechanics is weird to us because we're human-sized and quantum effects
are mostly gone at our scale. Therefore, the only language we have for
actually doing quantum mechanics is mathematics, so it makes sense to get a
firm grasp of the math first. Fortunately, the fundamentals of the math aren't
that difficult. I like to think of quantum mechanics as being 'mind-bendingly
simple' for that reason.

Scott Aaronson has a fascinating lecture on quantum mechanics seen as a branch
of probability theory:

<http://www.scottaaronson.com/democritus/lec9.html>

> Quantum mechanics is what you would inevitably come up with if you started
> from probability theory, and then said, let's try to generalize it so that
> the numbers we used to call "probabilities" can be negative numbers.

~~~
disgruntledphd2
That's a wonderful link. I know very little about quantum mechanics (or
physics in general) but I do know some linear algebra, and for me that was a
wonderful revelation. Thank you for sharing.

------
pokesomesmot
I don't understand why FA are so difficult for CS students to grasp.

I have the reverse problem. The concept of FA makes perfect sense. It's how I
naturally think of a computer. It's the theory stuff that is not based on
state machnes which I can't get my head around.

So my question is, what enlightenment would I attain if I understood all the
theory (instead of just the reality)?

When I write programs, I write state machines.

------
chrismaeda
You're supposed to realize that enlightenment is not computable by an FA.

------
Adrock
The answers given are great, especially the first.

It's also nice to be able to express solutions as clearly and succinctly as
you can with libraries like this:

<https://github.com/cdorrat/reduce-fsm>

Not enlightenment, just bliss...

------
subhro
Here is another set of lectures from IIT Madras India which helped me
understand what Automata is all about.

<http://www.nptel.iitm.ac.in/courses/106106049/>

------
pekk
If nothing else, it gives you an understanding of what regular expressions are
doing, and a basis for understanding about the Chomsky hierarchy.

------
wonderzombie
Any good links about automata? I'm afraid I don't know much about this just
yet, so I can't really appreciate it.

------
javajosh
It is to recognize the congnizing that you are doing about finite automata is
itself composed of finite automata.

~~~
jmduke
Not to be rude, but what do you mean by this?

~~~
javajosh
Recursion is the key to enlightenment. There are may ways to achieve this
recursion, and contemplation of finite automata is one of them. The point of
recursion happens when you realize that the thought process which is
considering finite automata is itself composed of finite automata. The
subjective experience of recursion leads to enlightenment.

~~~
dietrichepp
Chemical processes are not measurably discrete, so it is only a conjecture
that the universe could be modeled as a finite automaton.

Varying reference frames make it impossible to agree on an order for the input
our brains receive, even if we can think of it as discrete. Agreeing on the
state of a brain is also impossible, due to relativity.

Quantum entanglement makes it impossible to accurately model a portion of the
physical universe, such as a brain. If you want complete accuracy you must
model the whole universe or none of it.

I am aware of no accepted model of the universe that is deterministic. Finite
automata are deterministic, the brain and the universe are not. Look up
"hidden variables".

Only a more sophisticated model than finite automata could possibly be useful
for describing physical phenomena in general. All models are wrong, but finite
automata are not even useful for describing brains.

------
mcgwiz
Applications:

1\. deep understanding of regular expressions.

2\. how to model and reason about complex workflows and business processes.

------
robomartin
"Aha! moment". Well, I have to say that, for me, this came with the practice,
not the study, of FSM's and, in particular Turing Machines. I could not
imagine a world without them. Look around you.

While I studied FA formally it never really clicked until years later.
Sometimes you don't really learn until you are holding a cat by the tail.

I should say that I've always called them "FSM" when, in most cases, in
reality I was using a TM. A TM, of course, is also an FSM, so I'm at peace
with my loose use of the term.

I really started to use FSM's with great frequency while working on developing
hardware with FPGA's. Everything from reset modules to FIFO and SD/DD RAM
controllers and more benefit from FSM's. They greatly reduce complexity and
allow you to express very complex logic in code that can actually be followed
and understood. For some reason FSM's feel more "at home" in hardware rather
than software for me (although I use them extensively in software as well).
There's something about looking at the definition of an FSM's states and
realizing that it's a bunch of single bits (flip-flops) that makes it real:

    
    
        // Fictitious example
        parameter STATE_RESET      = 5'b00001;
        parameter STATE_STOP       = 5'b00010;
        parameter STATE_FORWARD    = 5'b00100;
        parameter STATE_TURN_RIGHT = 5'b01000;
        parameter STATE_TURN_LEFT  = 5'b10000;
    

Later, when you code the FSM --and if you've been doing this for a while-- you
can look at the code and almost literally see the flip-flops and latches
forming the structure:

    
    
        always @ (posedge SOME_CLK) begin
            case(state)
                STATE_RESET: begin
                    // Do something in this state
                end
                STATE_STOP: begin
                    // Do something in this state
                end
                STATE_FORWARD: begin
                    // Do something in this state
                end
                STATE_TURN_RIGHT: begin
                    // Do something in this state
                end
                STATE_TURN_LEFT: begin
                    // Do something in this state
                end
            endcase
        end
    

It's really cool. Geeking-out just thinking about it.

In the software front, everything from communications packet processors to
email address validation and menu processors benefit from using FSM's. I like
the application of FSM's to web app controllers where you can encode a lot of
knowledge and sophistication into your control module and not end-up with a
huge rats-nest of procedural code that is nearly impossible to understand and
maintain.

I have to admit being guilty of "thinking like an FSM" at times to the extent
that I see the opportunity to use them in almost every project, hardware or
software.

Again, today I could not imagine designing hardware or writing software
without FSM's.

~~~
csense
What's the logic behind defining your states as bitflags instead of enums? I
would typically write STATE_RESET = 0, STATE_STOP = 1, STATE_FORWARD = 2,
STATE_TURN_RIGHT = 3, STATE_TURN_LEFT = 4...

Unless, of course, you're doing an NFA and have a reason to superimpose states
(i.e. be in STATE_TURN_RIGHT and STATE_TURN_LEFT simultaneously).

~~~
robomartin
Ah, remember, this is hardware and, this is Verilog, not C.

What you are looking at is called "one-hot" encoding.

If you enumerate your states you are asking Verilog to infer a register to
hold your states. This also means that you have to have additional (slow)
combinatorial logic to identify which state you are in.

With one-hot encoding each state is represented by a single and discrete flip-
flop (FF) and no combinatorial logic is required. If you have 33 states the
state machine has 33 FF's and only one of them can be "hot" or set to "1" at
any given time.

One-hot encoding is faster, and offer a lot of other advantages (ease of
debugging, ease of optimization, timing closure, etc.).

Here's a good resource:

[http://www.xilinx.com/txpatches/pub/documentation/xactstep6/...](http://www.xilinx.com/txpatches/pub/documentation/xactstep6/hdlsynth.pdf)

Go directly to Appendix A.

~~~
csense
I've never actually done hardware design. I last looked at it a few years ago
and it seemed really confusing.

What I really want is an FPGA on a board like the Raspberry Pi, where I can
just plug in USB, network and power, copy-paste some code from a tutorial,
have it run, and start learning HDL from that point.

I want to be able to develop an FPGA program that can _maybe_ do a specific
bitwise computation faster than a CPU or GPU (like SHA hashes for bitcoin
mining, but this is just one example) and send inputs and outputs back and
forth with a regular computer. _Without_ also having to design and solder my
own circuit board in order to do it.

It seems, though, like as soon as you say the word "FPGA," people
automatically assume you have a ton of experience and equipment for building
your own circuit boards. Which I really don't. And learning this _on the same
project_ learning HDL seems like it would really make things kinda hard. "It
doesn't work" could mean anything from a solder blob shorting two wires, to
some screw-up earlier in the process having destroyed a component and now
it'll never work even if you do the rest of it correctly (and you have to
increase your budget to replace the now-fried chip), to a failure to
understand something about HDL, to some electromagnetic bug in the design of
the circuit (like "you need a capacitor here, you need an inductor there, your
resistor is 100x too big or too small")...a bug in the HDL of course...or it
could be a bug in the USB interface hardware/software I made on the board...or
in the custom USB driver I wrote (I've also never actually written a hardware
driver before) running on the general-purpose computer...In short, it seems
like, to get started teaching yourself hardware design, you have to have
approximately one university degree worth of hardware design knowledge
already.

Learning HDL, I want to be able to eliminate all of the above sources of error
but "if it doesn't work, it must be a bug in my HDL code."

Bootstrapping software programming through self-learning is easy enough that
probably at least tens of thousands of middle and high school kids do it on
their own every year (I was one of them). Bootstrapping GPU programming is a
little harder but still seems doable (I haven't actually done more than
dabbling, though). Bootstrapping FPGA _should_ be just as easy, but it isn't.

I haven't been able to find what hardware I should buy to do this, and I
haven't even been able to figure out what search terms I should be using. It's
been a few years since I looked, though, so maybe I should look again.

~~~
robomartin
Honestly, there's absolutely nothing that would prevent you from learning HDL.
There are a number of excellent development boards and tutorials. Start here:

<http://www.xilinx.com/university/students/index.htm>

The issue with doing higher-level work is that you really need to understand
circuit design and implementation. A lot of what you do in an FPGA is to type
out text that looks like code but in reality is a "secret contract" with the
compiler for it to "infer" the circuit you want. In many ways you could say
that there are idioms that you learn that will result in specific circuit
constructs once they go through one turn of the wheel.

Then there's the issue of optimization. Sometimes you just don't get the
performance you want and have to resort to, effectively, hand-wiring stuff in
code. Whether VHDL or Verilog, you have the ability to literally hand-wire
FPGA internals to build circuits that usually perform or place better than the
what the tools can do:

(sorry, this is long)

    
    
        module ADDER
        #(parameter WIDTH = 8)
        (
             input wire CLK,
             input wire CE,
            input wire RST,
            input wire CIN,
             input wire [WIDTH - 1:0] A,
            input wire [WIDTH - 1:0] B,
            output wire [WIDTH:0] SUM
        );
    
        genvar i;
    
        wire [WIDTH - 1:0] xor2;
        wire [WIDTH:0] cy;
        wire [WIDTH - 1:0] xorcy;
    
        assign cy[0] = CIN;
    
        generate
        for(i=0; i <= WIDTH; i=i+1) begin:BIT
            if(i != WIDTH)begin:_
                myXOR2 x(.O(xor2[i]), .I0(A[i]), .I1(B[i]));
                MUXCY  m(.O(cy[i+1]), .CI(cy[i]), .DI(A[i]), .S(xor2[i]));
                XORCY  xc(.O(xorcy[i]), .CI(cy[i]), .LI(xor2[i]));
                FDRE   f(.Q(SUM[i]),  .C(CLK), .CE(CE), .D(xorcy[i]),  .R(RST));
            end
            else begin:_
                FDRE   f(.Q(SUM[i]),  .C(CLK), .CE(CE), .D(cy[i]),  .R(RST));
            end
        end
        endgenerate
    
        //synthesis attribute RLOC of BIT[0]._.x  is X0Y0
        //synthesis attribute RLOC of BIT[1]._.x  is X0Y0
        //synthesis attribute RLOC of BIT[2]._.x  is X0Y1
        //synthesis attribute RLOC of BIT[3]._.x  is X0Y1
        //synthesis attribute RLOC of BIT[4]._.x  is X0Y2
        //synthesis attribute RLOC of BIT[5]._.x  is X0Y2
        //synthesis attribute RLOC of BIT[6]._.x  is X0Y3
        //synthesis attribute RLOC of BIT[7]._.x  is X0Y3
        //synthesis attribute RLOC of BIT[8]._.x  is X0Y4
        //synthesis attribute RLOC of BIT[9]._.x  is X0Y4
        //synthesis attribute RLOC of BIT[10]._.x is X0Y5
        //synthesis attribute RLOC of BIT[11]._.x is X0Y5
        //synthesis attribute RLOC of BIT[12]._.x is X0Y6
        //synthesis attribute RLOC of BIT[13]._.x is X0Y6
        //synthesis attribute RLOC of BIT[14]._.x is X0Y7
        //synthesis attribute RLOC of BIT[15]._.x is X0Y7
        //synthesis attribute RLOC of BIT[16]._.x is X0Y8
        //synthesis attribute RLOC of BIT[17]._.x is X0Y8
        //synthesis attribute RLOC of BIT[18]._.x is X0Y9
        //synthesis attribute RLOC of BIT[19]._.x is X0Y9
        //synthesis attribute RLOC of BIT[20]._.x is X0Y10
        //synthesis attribute RLOC of BIT[21]._.x is X0Y10
        //synthesis attribute RLOC of BIT[22]._.x is X0Y11
        //synthesis attribute RLOC of BIT[23]._.x is X0Y11
        //synthesis attribute RLOC of BIT[24]._.x is X0Y12
        //synthesis attribute RLOC of BIT[25]._.x is X0Y12
        //synthesis attribute RLOC of BIT[26]._.x is X0Y13
        //synthesis attribute RLOC of BIT[27]._.x is X0Y13
        //synthesis attribute RLOC of BIT[28]._.x is X0Y14
        //synthesis attribute RLOC of BIT[29]._.x is X0Y14
        //synthesis attribute RLOC of BIT[30]._.x is X0Y15
        //synthesis attribute RLOC of BIT[31]._.x is X0Y15
        <... a bunch more of this snipped due to HN message length constraints ...>
        endmodule
    
        //synthesis attribute LUT_MAP of myXOR2 is YES;  
        module myXOR2
        (
          output O,
          input I0,
          input I1
        );
    
        assign O = I0 ^ I1;
    
        endmodule
    

That's the kind of thing you have to do if you have to squeeze the last MHz in
performance out of an FPGA. That code was part of an FIR filter I designed
that, about ten years ago, could not break 150MHz using the "hey compiler, you
figure it out" approach. If I remember correctly, the hand-wired filter easily
did 200MHz.

------
dschiptsov
That you're one of them.)

------
martinced
It's interesting that both the question _and_ the answer do focus on pattern
matching. I maybe mistaken on this but that is really just one use of FSMs.

I've implement event-driven FSMs and to me the biggest "ah ah" moment was that
it was trivial to make a list of valid (or non valid) state transitions. I
used it in one particular case which was really complex (IMHO) to model and
were my code was quickly becoming a gigantic mess. I ended up rewriting that
part using an event-driven FSM and things became smooth.

Nowadays I don't like the 'S' in "FSM" that much anymore: I've moved to FP and
can't really say I'm missing mutability.

~~~
chas
I don't think you need to abandon the S. I think FSMs embody the core of
functional thinking. Structuring your computation as a FSM splits your code
into your current state and a combinatorial logic block that takes a current
state and outputs a new state along with some optional side-effects. Splitting
your computations into pure functions that hold state on their end-points
sounds very much like the philosophy behind FP.

