So far we have discussed three approaches to knowledge representation and inference: structured objects, logic, and rules.
Structured objects are useful for representing declarative information about collections of related objects/concepts, and in particular where there is a clear class hierarchy, and where you want to use inheritance to infer the attributes of objects in subclasses from the attributes of objects in the parent class. Early approaches tended to have poorly specified semantics but there are now some practical systems with a clear underlying semantics.
Structured objects are no good if you want to draw a wide range of different sorts of inferences, maybe using IF-THEN rules. For this you could use a logic-based approach, along with a theorem prover, or you could use a rule-based system. Logic-based approaches allow you to represent fairly complex things (involving quantification etc), and have a well-defined syntax, semantics and proof theory. However, no hacking is allowed in logic! If you can't represent something in your logic then that's too bad. General purpose theorem provers may also be very inefficient, especially once you get to more powerful logics. Rule-based systems tend to allow only relatively simple representations of the underlying facts in the domain, but may be more flexible, and often allow certainty values to be associated with rules and facts. While logic is primarily used in a declarative way, saying what's true in the world, rule-based systems (especially forward chaining systems) are concerned more with procedural knowledge - what to do when.
In all the the approaches it should be possible to add new facts (and rules) in a simple, incremental fashion, without rewriting the whole system. This is an important advantage compared with just writing a Pascal program which implicitly captures the knowledge. AI programs typically have a distinct knowledge base, to which new facts can be added as needed, capturing the rules and facts of the domain in question. Separate problem solving procedures may then access and possibly update that knowledge.
Whatever ``language'' you represent the knowledge in, certain things are important. First, it should be represented at the right level of abstraction - you want to be able to write a few general purpose facts/rules, not a whole lot of very specific ones. Next, it is helpful to write things in a way which allows new facts/rules to be added without radically changing the behaviour of the whole system. Preconditions of rules, for example, should be specified sufficiently precisely so that they won't inappopriately fire when new facts are added. Lots more issues are discussed in [Rich &Knight, 4.3].