```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 ``` ```# Lab 9 optional exercise #5   # cons pairs AND the empty list will be implemented as one-argument # lambdas (closures). There are 3 special arguments (messages): # the ISCONS argument returns true/false depending on whether the # closure actually represents a cons pair or "null", # the GETCAR argument returns the car of a pair, and GETCDR # returns the cdr of a pair. # These special argument names are defined as global variables # so they can be easily referenced.   new ISCONS := 1000; new GETCAR := 2001; new GETCDR := 2002;   # null is a function that just returns the fact that it's not # a cons pair!   new null := lambda msg {   ifelse msg = ISCONS     { ret := false; }     { "ERROR: illegal argument to null" } };   # cons is a curried 2-argument function that returns a lambda # for the pair. new cons := lambda a {   ret := lambda b {     # Now we have the 2 parts of the cons, a and b.     # Time to return a lambda which will retrieve them.     ret := lambda msg {       ifelse msg = ISCONS { ret := true; }       { ifelse msg = GETCAR { ret := a; }         { ifelse msg = GETCDR { ret := b; }           { "ERROR: illegal message to cons pair" }}}     };   }; };   # shortcut methods for coar and cdr new car := lambda P { ret := P@GETCAR; }; new cdr := lambda P { ret := P@GETCDR; };   # predicate to test whether something is a cons pair or null new is_cons := lambda P { ret := P@ISCONS; };   # Now we can do something with these: let's make a list new L1 := cons@1 @ (cons@2 @ (cons@3 @ (cons@4@null) ) );   write car@L1; # prints 1 write car@(cdr@L1); # prints 2   # Function to sum the numbers in a list new sum := lambda L {   ifelse is_cons@L     { ret := car@L + sum@(cdr@L); }     { ret := 0; } };   write sum@L1; # prints 1+2+3+4 = 10```