That's probably a vague question but allow me to try and give an example:My compiler does transformations on HTML (from HTML to HTML). It scans a flattened DOM tree, and relies on lookbehinds (on elements pushed onto a stack) to decide what transformation to apply. I can give more detail if necessary but I don't want to lose the reader. Can such logic be alternatively implemented with no mutable state? I have become a big believer in functional programming and have made it a point to make my code as functional-style as possible. I don't like loops that perform actions based on the content of a previous iteration, by saving the information from a previous iteration in stacks or booleans. I need to augment the functionality of this routine and will probably tip the code from being just about understandable to only the author will understand this, everyone else don't touch.But I have little background in compiler theory & development so am wondering if the problem domain necessitates mutable state in practice.
Is it possible to write an HTML compiler with no mutable state?
compilers;pushdown automata;functional programming
In theory, any program can be treated as functional by treating every operation as replace the world with a world this piece of state replaced by a different value. In practice ... this actually works pretty well.Your code will look something like:root_node = parse_html()for each operation:    root_node = root_node.replace_using_operation(operation)For a leaf or node that you know won't be affected by this operation, replace_using_operation looks like:fn replace_using_operation(self, op):    return selfFor the typical non-leaf case, replace_using_operation will look like:fn replace_using_operation(self, op):    children = new List<Node>();    # pedantically, this is not functional, but realistically it is.    # if your language has generators or a iterator map function you can    # make it purely functional, but most people find this easier to read.    for each ch in self.children:        children.append(ch.replace_using_operation(op))    new_self = new Node(children)    delete self    return new_selfOf course, depending on what knowledge you have of the operation, you might want to perform different operations on some children. Also note that you're perfectly free to pass additional arguments (including snapshots of other branches of the tree - just remember you don't own them) or to have entirely separate replace_* functions instead of passing operation as an argument.This code is only a very rough skeleton, after all.