E [[0]]s = (0,s)
    E [[1]]s = (1,s)
    E [[read]](m, i, o) = if (empty i) then error, 
                                        else (hd i, (m, tl i,  o))
    E [[I]](m, i, o) = if m i = unbound  then  error, 
                                          else  (m I, (m, i, o))
    E [[E1 + E2]]s = if (E [[E1]]s = (v1,s1) & E [[E2]]s1 = (v2,s2))  
                                then (v1 + v2, s2)
                                else error
    E [[fn x => E]]s  = fun n in Nat. E [[E]](s[n/x])
    E [[E1 (E2)]]s = E [[E1]]s (E [[E2]]s)
Note
difference in meaning of function here from that of operational
semantics!
Define B: BoolExp -> [State -> [[Value x State] + {error}]] by:
    B [[true]]s = (true,s)
    
    B [[false]]s = (false,s)
    
    B [[not B]]s = if  B [[B]]s = (v,s') then  (not v, s'), 
                                          else  error
                        
    B [[E1 = E2]]s = if  (E [[E1]]s = (v1,s1)  & E [[E2]]s1 = (v2,s2))  
                               then  (v1 = v2, s2)
                               else error
Define C : Command -> [State -> [State + {error}]] by:
    C [[I := E]]s = if  E [[E]]s = (v,(m,i,o)) then (m[v/I],i,o)
                                                else  error
        where m' = m[v/I] is identical to m except the value of I is v.
    C [[output E]]s = if  E [[E]]s = (v,(m,i,o)) then (m,i,v.o)
                                                  else  error
        where  v.o  is the result of attaching  v  to the front of  o.
    C [[if E then C1 else C2]]s = if  B [[B]]s = (v,s')  
                                            then  if  v  then  C [[C1]]s'
                                                         else  C [[C2]]s'
                                            else  error
                                            
    C [[while E do C]]s = if  B [[B]]s = (v,s') 
                                     then if v then if  C [[C]]s' = s''  
                                                    then C [[while E do C]]s''
                                                    else  error
                                               else  s'
                                     else  error
                                   
    C [[C1; C2]]s = if  C [[C1]]s = error then error
                                           else  C [[C2]] ( C [[C1]]s)
End
Tiny
Notice that definition of while is a recursive definition.
Thus, if B [[B]] s = True and s' = C [[S]] s, then C[[while B do S]]s = C [[while B do S]]s'
Solution involves computing what is known as least fixed points.
Denotational semantics gained considerable popularity over last 15 years.
Many people consider denotational semantics as most appropriate for studying meaning of language independent of its implementation.
Good for looking at trade-offs between alternate forms of similar constructs.
Which is best?
No good answer, since have different uses.
Complementary definitions. Can be compared for consistency.
Programming language definitions usually still given in English. Formal definitions often too hard to understand or require too much sophistication. Gaining much more acceptance. Now relatively standard intro graduate course in CS curricula.
Some success at using formal semantics (either denotational or operational) to automate compiler construction (similar to use of formal grammars in automatic parser generation).
Semantic definitions have also proved to be useful in understanding new programming constructs.
What is logic programming? -
"A constructive proof that for every list L there is a corresponding sorted list S composed of the same elements as L yields an algorithm for sorting a list."
Philosophy is shared by others not working on "logic programming", e.g. Constable at Cornell, Martin-Löf in Sweden, Calculus of Constructions group in France. These groups want to extract (more traditional) program from constructive proofs.
Very-High-Level Languages - non-procedural
State what must be done, not how to do it. Idea is to separate logic from control. (Examples later)
Developed in 1972 by Alain Colmerauer in Marseilles.
Text has an excellent introduction to PROLOG. I will presume you have read it and concentrate on examples!
Often best to start out as thinking of Prolog in terms of language for working with a data base.
Three types of statements:
Facts (or hypotheses):
    father(albert,jeffrey). 
Rules
(or conditions): 
    grandparent(X,Z) :- parent(X,Y),parent(Y,Z).    
        (read ":-" as "if")Queries (or goals):
    ?-grandparent(X,jeffrey). 
Should think of language as non-deterministic (or non-procedural). Looks for all answers satisfying predicate.
father(john,ralph). 
father(mary,ralph). 
father(ralph,bill). 
  
mother(john,sue). 
mother(mary,sue). 
mother(ralph,joan). 
  
male(john). 
male(ralph). 
male(bill). 
  
female(mary). 
female(sue). 
  
/* RULES */ 
is_mother(M):-mother(Y,M). 
  
parent(X,M):-mother(X,M). 
parent(X,F):-father(X,F). 
  
parents(X,M,F):-mother(X,M),father(X,F). 
  
sister(X,S):-female(S),parents(X,M,F),parents(S,M,F),S\=X. 
  
ancester(X,Y):-parent(X,Y). 
ancester(X,Y):-parent(X,Z),ancester(Z,Y). 
/***********************newsort.pro**************************/ 
 
/********************Selection Sort*******************/ 
  
sel_sort([],[]). 
  
sel_sort(L,[Small|R]) :- 
        smallest(L,Small) ,  
        delete(Small,L,Rest) ,  
        sel_sort(Rest,R) . 
  
/* smallest(List, Small) results in Small being the smallest element in List. */ 
  
smallest([Small],Small) . 
  
smallest([H|T],Small) :- 
          smallest(T,Small) ,  
          Small=<H. 
smallest([H|T],H). 
  
/* delete(Elt,List,Result) has Result as List after deleting Elt. */ 
  
delete(Elt,[],[]) . 
  
delete(Elt,[Elt|T],T) . 
  
delete(Elt,[H|T],[H|NuTail]) :- 
        delete(Elt,T,NuTail) . 
  
/*******************Insertion Sort********************/ 
  
ins_sort([],[]) . 
  
ins_sort([H|T],Sorted) :- 
        ins_sort(T,Rest),  
        insert(H,Rest,Sorted) . 
  
/* insert(Elt,List,Result) - if List is sorted, Result is obtained by putting 
     Elt where it fits in order in List. */ 
  
insert(Elt,[],[Elt]) . 
  
insert(Elt,[H|T],[Elt,H|T]) :- 
        (Elt=<H) . 
  
insert(Elt,[H|T],[H|Sorted]) :- 
        insert(Elt,T,Sorted) . 
  
/* **********Quick Sort************** */ 
  
/* sep(List,Key,Less,More) separates the List into the set of elements less 
   than or equal to Key (in Less) and those greater than or equal to Key 
   (in More) */ 
  
sep([],Key,[],[]) .         
  
sep([H|T],Key,Less,[H|More]) :- 
        (H>Key) ,  
        sep(T,Key,Less,More) . 
  
sep([H|T],Key,[H|Less],More) :- 
        (H=<Key) ,  
        sep(T,Key,Less,More) . 
  
quick_sort([],[]) . 
  
quick_sort([H|T],Sorted) :- 
        sep(T,H,Less,More) ,  
        quick_sort(Less,L_sorted) ,  
        quick_sort(More,M_sorted) ,  
        concat(L_sorted,[H|M_sorted],Sorted) . 
  
/* concat(First, Second, List) results in List = concatenation of First 
and Second. */ 
  
concat([],L,L) . 
  
concat([H|T],L,[H|C]) :- concat(T,L,C) . 
/************************************************
Can take advantage of reversibility since computing with relations rather 
than functions. 
********************Permutations*******************/ 
append([],L,L) . 
  
append([H|T],L,[H|R]) :- append(T,L,R) . 
permute([],[]) . 
  
permute(L,[H|T]) :- 
        append(V,[H|U],L) , 
            /* V,U stand for the part of L before and after H */  
        append(V,U,W) ,  
        permute(W,T) . 
  
***********************************************
Ex.
father(john,ralph). father(mary,ralph). father(ralph,bill). mother(john,sue). mother(mary,sue). mother(ralph,joan). /* RULES */ is_mother(M):-mother(Y,M). parent(X,M):-mother(X,M). parent(X,F):-father(X,F). ancester(X,Y):-parent(X,Y). ancester(X,Y):-parent(X,Z),ancester(Z,Y). ?-ancester(X,joan).backtracking
First succeeds with X = ralph
later w/X= john, mary
Usually in prefix, can force to be in infix or postfix and give precedence as well.
Ex. +, - ,*,/
2+3*5 abbreviates +(2,*(3,5))
operations are not evaluated
Better to think of operations as forming tags on values -
Relations
=, \=, <, >, =<, >= (note order of composite relations) are evaluated.
Ex. digit(N):- N>=0,N<10.
Example of using operations.
treesort
tree is either nil or is of form maketree(tree1,X,tree2).
Write program to do treesort! Very much like ML program.
Ex. area(L,W,A):-A is L*W.
Can only compute A from L,W - not reversible.