Be organised Lecture 9 Programming Methodology and Style • Think and plan before you start writing the actual program. • For a medium or large-size program, try top-down design (see later). • Aim for simplicity and clarity, rather than obscure Contents efficiency. (If efficiency becomes important later, that is • Some general dos and don’ts of program- the time to worry about it.) ming. • Consider maintainability : what will it be like to make • Some specific Prolog advice sense of the program after a few weeks/months/years? what will it be like to try to amend it after such a period? • What is top-down design? what if it were someone else doing this? (After only a few weeks, you will feel like someone else). (See Clocksin & Mellish Chapter 8) 2 “Introduction to Artificial Intelligence Programming”, School of Informatics Layout and Comments An example of commenting Put a header at the top, optionally some commentary between • Make your text easy to read. clauses or at the right. % count_atoms/2(+List, -CountOfAtoms) • Not too much on each line. % • Indentation to show nesting or levels. % Succeeds where CountOfAtoms is % instantiated to a list containing the • Appropriate commenting. % count of each of the atoms in List, % in the following form: % % [a=2, b=3, c=4] % % Add an accumulator. count_atoms(List, CountList) :- count_atoms(List, [], CountList). ETC ... Notation for parameters: if parameter must be instantiated on call: + if parameter is not instantiated on call: - if parameter may or may not be instantiated on call: ? 3 4 “Introduction to Artificial Intelligence Programming”, School of Informatics “Introduction to Artificial Intelligence Programming”, School of Informatics
Vigilance and pessimism Locality and modularity • Watch for special cases (lists being empty, variables being • Predicate definitions should be short. uninstantiated, etc.) • Predicate definitions should be simple. • Assume any input from users could be malformed. • The exact behaviour of each predicate should be thought • For each predicate, consider what would happen if it were about and documented (see commenting). given the wrong sort of data, or if some intermediate • It should be possible to replace any predicate definition computation had an unexpected result. with another definition that has the same behaviour (but • (Prolog) Think what would happen on a REDO different internally) without affecting the rest of the (backtracking), and place cuts accordingly. program. 5 6 “Introduction to Artificial Intelligence Programming”, School of Informatics “Introduction to Artificial Intelligence Programming”, School of Informatics Prolog: avoiding confusion Prolog: choices as clauses Where your program has to make a choice, define a predicate • Having different predicates with the same name but to make this choice, so that separate options correspond to different arity can be confusing. Either avoid this, or do it clauses of that predicate. That is, when in the middle of only when the two predicates are closely related and not writing a predicate definition you find that there is more than easily confused. (More generally, choose variable and one course of action – invent another predicate to be invoked predicate names to be helpful.) at this point. • Don’t have too many arguments for a predicate. If a (Sometimes the semi-colon disjunction operator can be predicate definition has grown to have (for example) 12 useful, but such cases are the exception.) arguments, consider whether some of the arguments can be clustered into data structures and so passed as a single item. • If a variable is “singleton” (i.e. mentioned only once in the clause), then either use the underscore, or give it a name starting with an underscore; the latter means it can still have a mnemonic name to help you. Then you know that warnings from the system about singleton variables will always mean something is wrong. 7 8 “Introduction to Artificial Intelligence Programming”, School of Informatics “Introduction to Artificial Intelligence Programming”, School of Informatics
Prolog: unify in the head Top-down design If a predicate is to stipulate that two values are to be unified, A simple but very useful way to organise the planning of a then, if these are arguments, do the unification “in the head of program. the clause”, not by using “=” in the body. E.g. • Start from the main task. ismember(Item, [Item|_]). • Split it into a small number of slightly simpler tasks. not: • For each of these tasks in turn, do the same splitting up. ismember(Item, [X|_]):- X = Item. • Eventually decompose the whole task into a hierarchy of (There may be cases where the unification needs to be tasks and subtasks, with those “at the bottom” being postponed, but don’t use the “=” option unnecessarily.) extremely simple (and so easily implementable). Original Problem Task 1 Task 2 Task 3 Task 1.1 Task 1.2 Task 2.1 Task 2.2 Task 3.1 Task 3.2 Task 3.3 9 10 “Introduction to Artificial Intelligence Programming”, School of Informatics “Introduction to Artificial Intelligence Programming”, School of Informatics Deciding parameters Summary • Omit parameters from early sketches. • Organise • Once you have units which correspond to predicates, work • Layout and comments out what the parameters are. • Assume the worst • Decide what information needs to flow between parts of • Keep it local the program. • Avoid confusing names and parameters • Think of the information flow as “input” or “initial” • Choices are clauses parameters (instantiated when the CALL happens) and “output” or “result” parameters (unininstantiated on • Put unifications in the head CALL, to be instantiated when the EXIT happens). • Top-down design makes life easier 11 12 “Introduction to Artificial Intelligence Programming”, School of Informatics “Introduction to Artificial Intelligence Programming”, School of Informatics
Recommend
More recommend