Difference between revisions of "LISP"

From ACSL Category Descriptions
Jump to navigation Jump to search
 
(26 intermediate revisions by 4 users not shown)
Line 1: Line 1:
LISP is one of the simplest computer languages in terms of syntax and semantics, and also one of the most powerful.  It was developed in the mid-1950’s by John McCarthy at M.I.T. as a “LISt Processing language. It has been historically used for virtually all Artificial Intelligence programs and is often the environment of choice for applications which require a powerful interactive working environment.  LISP presents a very different way to think about programming from the “algorithmic” languages, such as Python, C++, and Java.
LISP is one of the simplest computer languages in terms of syntax and semantics, and also one of the most powerful.  It was developed in the mid-1950's by John McCarthy at M.I.T. as a "LISt Processing language." It has been historically used for virtually all Artificial Intelligence programs and is often the environment of choice for applications which require a powerful interactive working environment.  LISP presents a very different way to think about programming from the "algorithmic" languages, such as Python, C++, and Java.


== Syntax ==
== Syntax ==
Line 7: Line 7:
:<code>(23 (this is easy) hello 821)</code>
:<code>(23 (this is easy) hello 821)</code>


The elements in the list, which are not lists, are called “atoms. For example, the atoms in the list above are: 23, ‘this, ‘hello, 821, ‘easy, and ‘is.  Literals are identified with a single leading quote.  Everything in LISP is either an atom or a list (but not both).  The only exception is “NIL,which is both an atom and a list.  It can also be written as ()– a pair of parentheses with nothing inside.
The elements in the list, which are not lists, are called "atoms." For example, the atoms in the list above are: 23, 'this, 'hello, 821, 'easy, and 'is.  Literals are identified with a single leading quote.  Everything in LISP is either an atom or a list (but not both).  The only exception is "NIL," which is both an atom and a list.  It can also be written as "()" – a pair of parentheses with nothing inside.


All statements in LISP are function calls with the following syntax: (function arg1 arg2 arg3 … argn).  To evaluate a LISP statement, each of the arguments (possibly functions themselves) are evaluated, and then the function is invoked with the arguments.  For example, (MULT (ADD 2 3) (ADD 1 4 2)) has a value of 35, since (ADD 2 3) has a value of 5, (ADD 1 4 2) has a value of 7, and (MULT 5 7) has a value of 35.  Some functions have an arbitrary number of arguments; others require a fixed number.  All statements return a value, which is either an atom or a list.  
All statements in LISP are function calls with the following syntax: (function arg1 arg2 arg3 … argn).  To evaluate a LISP statement, each of the arguments (possibly functions themselves) are evaluated, and then the function is invoked with the arguments.  For example, (MULT (ADD 2 3) (ADD 1 4 2)) has a value of 35, since (ADD 2 3) has a value of 5, (ADD 1 4 2) has a value of 7, and (MULT 5 7) has a value of 35.  Some functions have an arbitrary number of arguments; others require a fixed number.  All statements return a value, which is either an atom or a list.


== Basic Functions (SET, SETQ, EVAL, ATOM) ==
== Basic Functions (SET, SETQ, EVAL, ATOM) ==


We may assign values to variables using the function SET.  For example, the statement (SET ’test 6) would have a value of a 6, and (more importantly, however) would also cause the atom ‘test to be bound to the atom 6.  Observe the following examples:
We may assign values to variables using the function SET.  For example, the statement (SET 'test 6) would have a value of a 6, and (more importantly, however) would also cause the atom 'test to be bound to the atom 6.  The function SETQ is the same as SET, but it causes LISP to act as if the first argument was quoted. 
Observe the following examples:


TABLE
:{| class="wikitable" style="text-align: left"
!Statement || Value || Comment
|-
|(SET 'a (MULT 2 3))
|6
|a is an atom with a value of 6
|-
|(SET 'a '(MULT 2 3))
|(MULT 2 3)
|a is a list with 3 elements
|-
|(SET 'b 'a)
|a
|b is an atom with a value of the character a
|-
|(SET 'c a)
|(MULT 2 3)
|c is a list with 3 elements
|-
|(SETQ EX (ADD 3 (MULT 2 5)))
|13
|The variable EX has a value of 13
|-
|(SETQ VOWELS '(A E I O U))
|(A E I O U)
|VOWELS is a list of 5 elements
|}


The function SETQ is the same as SET, but it causes LISP to act as if the first argument was quoted.  The function EVAL returns the value of its argument, after it has been evaluated.  For example, (SETQ z (ADD 2 3)) has a value of the list (ADD 2 3); the function (EVAL ’z) has a value of (ADD 2 3); the function (EVAL z) has a value of 5 (but the binding of the atom z has not changed).  In this last example, you can think of z being “resolved” twice: once because it is an argument to a function and LISP evaluates all arguments to functions before the function is invoked, and once when the function EVAL is invoked to resolve arguments.  The function ATOM can be used to tell whether an item is an atom or a list. Consider the following examples:
The function EVAL returns the value of its argument, after it has been evaluated.  For example, (SETQ z '(ADD 2 3)) has a value of the list (ADD 2 3); the function (EVAL 'z) has a value of (ADD 2 3); the function (EVAL z) has a value of 5 (but the binding of the atom z has not changed).  In this last example, you can think of z being "resolved" twice: once because it is an argument to a function and LISP evaluates all arguments to functions before the function is invoked, and once when the function EVAL is invoked to resolve arguments.  The function ATOM can be used to determine whether an item is an atom or a list. It returns either "true", or "NIL" for false. Consider the following examples:


TABLE
:{| class="wikitable" style="text-align: left"
!Statement || Value || Comment
|-
|(SETQ p '(ADD 1 2 3 4))
|(ADD 1 2 3 4)
|p is a list with 5 elements
|-
|(ATOM 'p)
|true
|The argument to ATOM is the atom p
|-
|(ATOM p)
|NIL
|Because p is not quoted, it is evaluated to the 5-element list.
|-
|(EVAL p)
|10
|The argument to EVAL is the value of p; the value of p is 10.
|}


== List Functions (CAR, CDR, REVERSE, CONS)==
== List Functions (CAR, CDR, CONS, REVERSE)==


The two most famous LISP functions are CAR and CDR (pronounced: could-er), named after registers of a now long-forgotten IBM machine on which LISP was first developed.  The function (CAR x) returns the first item of the list x (and x must be a list or an error will occur); (CDR x) returns the list without its first element (again, x must be a list).  The function CONS takes two arguments, of which the second must be a list.  It returns a list which is composed by placing the first argument as the first element in the second argument’s list.  The function REVERSE returns a list which is its arguments in reverse order.   
The two most famous LISP functions are CAR and CDR (pronounced: could-er), named after registers of a now long-forgotten IBM machine on which LISP was first developed.  The function (CAR x) returns the first item of the list x (and x must be a list or an error will occur); (CDR x) returns the list without its first element (again, x must be a list).  The function CONS takes two arguments, of which the second must be a list.  It returns a list which is composed by placing the first argument as the first element in the second argument's list.  The function REVERSE returns a list which is its arguments in reverse order.   


The CAR and CDR functions are used extensively to grab specific elements of a list or sublist, that there's a shorthand for this: (CADR x) is the same as (CAR (CDR x)), (CAADDAR x) is a shorthand for (CAR (CAR (CDR (CDR (CAR x))))), and so on.
The CAR and CDR functions are used extensively to grab specific elements of a list or sublist, that there's a shorthand for this: (CADR x) is the same as (CAR (CDR x)), which retrieves the second element of the list x; (CAADDAR x) is a shorthand for (CAR (CAR (CDR (CDR (CAR x))))), and so on.


The following examples illustrate the use of CAR, CDR, REVERSE, and CONS:
The following examples illustrate the use of CAR, CDR, CONS, and REVERSE:
 
:{| class="wikitable" style="text-align: left"
!Statement || Value
|-
|(CAR '(This is a list))
|This
|-
|(CDR '(This is a list))
|(is a list)
|-
|(CONS 'red '(white blue))
|(red white blue)
|-
|(SETQ z (CONS '(red white blue) (CDR '(This is a list))))
|((red white blue) is a list)
|-
|(REVERSE z)
|(list a is (red white blue))
|-
|(CDDAR z)
|(blue)
|}


TABLE
== Arithmetic Functions (ADD, MULT, ...)==


== Arithmetic Functions ==
As you have probably already figured out, the function ADD simply summed its arguments.  We'll also be using the following arithmetic functions:


As you have probably deduced, the function ADD simply summed its arguments.  We’ll also be using the following arithmetic functions:
:{| class="wikitable" style="text-align: left"
!'''Function''' || '''Result'''
|-
|(ADD x1 x2 …)
|sum of all arguments
|-
|(SUB a b)
|a-b
|-
|(MULT x1 x2 …)
|product of all arguments
|-
|(DIV a b)
|a/b
|-
|(SQUARE a)
|a*a
|-
|(EXP a n)
|a<sup>n</sup>
|-
|(EQ a b)
|true if a and b are equal, NIL otherwise
|-
|(POS a)
|true if a is positive, NIL otherwise
|-
|(NEG a)
|true if a is negative, NIL otherwise
|-
|}


TABLE
Functions ADD, SUB, MULT, and DIV can be written as their common mathematical symbols, +, -, *, and /.  Here are some examples of these functions:


TABLE
:{| class="wikitable"
!'''Statement''' || '''Value'''
|-
|(ADD (EXP 2 3) (SUB 4 1) (DIV 54 4))
|24.5
|-
|(- (* 3 2) (- 12 (+ 1 2 1)))
| -2
|-
|(ADD (SQUARE 3) (SQUARE 4))
|25
|}


== User-defined Functions ==
== User-defined Functions ==


LISP also allows us to create our own functions using the DEF function. (We will sometimes use DEFUN rather than DEF, as it is a bit more standard terminology.)  For example,
LISP also allows us to create our own functions using the DEF function. (We will sometimes use DEFUN rather than DEF, as it is a bit more standard terminology.)  For example,
  (DEF SECOND (parms) (CAR (CDR parms)))
  (DEF SECOND (args) (CAR (CDR args)))
defines a new function called SECOND which operates on a single parameter named “parms”.  SECOND will take the CDR of the parameter and then the CAR of that result.  So, for example:
defines a new function called SECOND which operates on a single parameter named "args".  SECOND will take the CDR of the parameter and then the CAR of that result.  So, for example:
(SECOND (a b c d e))
(SECOND '(a b c d e))
would first CDR the list (yielding (b c d e)) and then CAR the result.  So the value would be the single character “b”.  Consider the following program fragment:
would first CDR the list to give (b c d e), and then CAR that value returning the single character "b".  Consider the following program fragment:
  (SETQ X (a c s l))
  (SETQ X '(a c s l))
  (DEF WHAT(parms) (CONS parms (REVERSE (CDR parms))))
  (DEF WHAT(args) (CONS args (REVERSE (CDR args))))
  (DEF SECOND(parms) (CONS (CAR (CDR parms)) NIL))
  (DEF SECOND(args) (CONS (CAR (CDR args)) NIL))


The following chart illustrates the use of the user-defined functions WHAT and SECOND:
The following chart illustrates the use of the user-defined functions WHAT and SECOND:


:{| class="wikitable"
:{| class="wikitable"
!Statement || Value  
!Statement || Value
|-
|-
|(WHAT X) || ((a c s l) l s c)
|(WHAT X) || ((a c s l) l s c)
Line 72: Line 180:
Questions from this topic will typically present a line of LISP code or a short sequence of statements and ask what is the value of the (final) statement.
Questions from this topic will typically present a line of LISP code or a short sequence of statements and ask what is the value of the (final) statement.


===Problem 1===
=== Problem 1 ===


Evaluate the following expression. <code>(EXP (MULT 2 (SUB 5 (DIV (ADD 5 3 4) 2)) 3) 3)</code>
Evaluate the following expression. <code>(MULT (ADD 6 5 0) (MULT 5 1 2 2) (DIV 6 (SUB 2 5)))</code>


'''Solution:'''
'''Solution:'''
  (EXP (MULT 2 (SUB 5 (DIV (ADD 5 3 4) 2)) 3) 3)
  (MULT (ADD 6 5 0) (MULT 5 1 2 2) (DIV 6 (SUB 2 5)))
(EXP (MULT 2 (SUB 5 (DIV 12 2)) 3) 3)
  (MULT 11 20  (DIV 6 -3))
  (EXP (MULT 2 (SUB 5 6) 3) 3)
  (MULT 11 20 -2)
  (EXP (MULT 2-1 3) 3)
  -440
(EXP –6 3)
  -216


=== Problem 2===
=== Problem 2 ===


Evaluate:  <code>(CDR ((2 (3))(4 (5 6) 7)))</code>
Evaluate the following expression:  <code>(CDR '((2 (3))(4 (5 6) 7)))</code>


'''Solution:'''
'''Solution:'''
Line 92: Line 198:
((4 (5 6) 7)), a list with one element.
((4 (5 6) 7)), a list with one element.


=== Problem 3===
=== Problem 3 ===


Consider the following program fragment:
Consider the following program fragment:
<syntaxhighlight>
(SETQ X '(RI VA FL CA TX))
(SETQ X (RI VA FL CA TX))
(CAR (CDR (REVERSE X)))
(CAR (CDR (REVERSE X)))
</syntaxhighlight>
What is the value of the CAR expression?  
What is the value of the CAR expression?  


'''Solution:'''
'''Solution:'''
The first statement binds variable X to the list (RI VA FL CA TX).
The first statement binds variable X to the list '(RI VA FL CA TX).
The REVERSE of this list is (TX CA FL VA RI)
The REVERSE of this list is '(TX CA FL VA RI)
whose CDR is (CA FL VA RI).  The CAR of this list is just the atom CA (without the quote).
whose CDR is '(CA FL VA RI).  The CAR of this list is just the atom CA (without the quote).
 
<!--
 
Too scary of a sample problem! --marc 9/3/2018


===Problem 4===
=== Problem 4 ===


Given the function definitions for HY and FY as follows:
Given the function definitions for HY and FY as follows:
Line 112: Line 220:
   (DEFUN FY(PARM) (CAR (HY (CDR PARM))))
   (DEFUN FY(PARM) (CAR (HY (CDR PARM))))
What is the value of the following?
What is the value of the following?
     (FY (DO RE (MI FA) SO))
     (FY '(DO RE (MI FA) SO))


'''Solution:'''
'''Solution:'''
To evaluate (FY (DO RE (MI FA) SO)), we must evaluate
To evaluate (FY '(DO RE (MI FA) SO)), we must evaluate
     (CAR (HY (CDR (DO RE (MI FA) SO)))).
     (CAR (HY (CDR '(DO RE (MI FA) SO)))).
Thus, HY is invoked with  
Thus, HY is invoked with  
     PARM = (RE (MI FA) SO), and we evaluate
     PARM = '(RE (MI FA) SO), and we evaluate
     (REVERSE (CDR (RE (MI FA) SO)))
     (REVERSE (CDR '(RE (MI FA) SO)))
This has a value of (SO (MI FA)) which is returned to FY.  FY now takes the CAR of this which is SO (without the quotes).
This has a value of (SO (MI FA)) which is returned to FY.  FY now takes the CAR of this which is SO (without the quotes).
-->


== Video Resources ==
== Video Resources ==

Latest revision as of 05:45, 11 February 2023

LISP is one of the simplest computer languages in terms of syntax and semantics, and also one of the most powerful. It was developed in the mid-1950's by John McCarthy at M.I.T. as a "LISt Processing language." It has been historically used for virtually all Artificial Intelligence programs and is often the environment of choice for applications which require a powerful interactive working environment. LISP presents a very different way to think about programming from the "algorithmic" languages, such as Python, C++, and Java.

Syntax

As its name implies, the basis of LISP is a list. One constructs a list by enumerating elements inside a pair of parentheses. For example, here is a list with four elements (the second element is also a list):

(23 (this is easy) hello 821)

The elements in the list, which are not lists, are called "atoms." For example, the atoms in the list above are: 23, 'this, 'hello, 821, 'easy, and 'is. Literals are identified with a single leading quote. Everything in LISP is either an atom or a list (but not both). The only exception is "NIL," which is both an atom and a list. It can also be written as "()" – a pair of parentheses with nothing inside.

All statements in LISP are function calls with the following syntax: (function arg1 arg2 arg3 … argn). To evaluate a LISP statement, each of the arguments (possibly functions themselves) are evaluated, and then the function is invoked with the arguments. For example, (MULT (ADD 2 3) (ADD 1 4 2)) has a value of 35, since (ADD 2 3) has a value of 5, (ADD 1 4 2) has a value of 7, and (MULT 5 7) has a value of 35. Some functions have an arbitrary number of arguments; others require a fixed number. All statements return a value, which is either an atom or a list.

Basic Functions (SET, SETQ, EVAL, ATOM)

We may assign values to variables using the function SET. For example, the statement (SET 'test 6) would have a value of a 6, and (more importantly, however) would also cause the atom 'test to be bound to the atom 6. The function SETQ is the same as SET, but it causes LISP to act as if the first argument was quoted. Observe the following examples:

Statement Value Comment
(SET 'a (MULT 2 3)) 6 a is an atom with a value of 6
(SET 'a '(MULT 2 3)) (MULT 2 3) a is a list with 3 elements
(SET 'b 'a) a b is an atom with a value of the character a
(SET 'c a) (MULT 2 3) c is a list with 3 elements
(SETQ EX (ADD 3 (MULT 2 5))) 13 The variable EX has a value of 13
(SETQ VOWELS '(A E I O U)) (A E I O U) VOWELS is a list of 5 elements

The function EVAL returns the value of its argument, after it has been evaluated. For example, (SETQ z '(ADD 2 3)) has a value of the list (ADD 2 3); the function (EVAL 'z) has a value of (ADD 2 3); the function (EVAL z) has a value of 5 (but the binding of the atom z has not changed). In this last example, you can think of z being "resolved" twice: once because it is an argument to a function and LISP evaluates all arguments to functions before the function is invoked, and once when the function EVAL is invoked to resolve arguments. The function ATOM can be used to determine whether an item is an atom or a list. It returns either "true", or "NIL" for false. Consider the following examples:

Statement Value Comment
(SETQ p '(ADD 1 2 3 4)) (ADD 1 2 3 4) p is a list with 5 elements
(ATOM 'p) true The argument to ATOM is the atom p
(ATOM p) NIL Because p is not quoted, it is evaluated to the 5-element list.
(EVAL p) 10 The argument to EVAL is the value of p; the value of p is 10.

List Functions (CAR, CDR, CONS, REVERSE)

The two most famous LISP functions are CAR and CDR (pronounced: could-er), named after registers of a now long-forgotten IBM machine on which LISP was first developed. The function (CAR x) returns the first item of the list x (and x must be a list or an error will occur); (CDR x) returns the list without its first element (again, x must be a list). The function CONS takes two arguments, of which the second must be a list. It returns a list which is composed by placing the first argument as the first element in the second argument's list. The function REVERSE returns a list which is its arguments in reverse order.

The CAR and CDR functions are used extensively to grab specific elements of a list or sublist, that there's a shorthand for this: (CADR x) is the same as (CAR (CDR x)), which retrieves the second element of the list x; (CAADDAR x) is a shorthand for (CAR (CAR (CDR (CDR (CAR x))))), and so on.

The following examples illustrate the use of CAR, CDR, CONS, and REVERSE:

Statement Value
(CAR '(This is a list)) This
(CDR '(This is a list)) (is a list)
(CONS 'red '(white blue)) (red white blue)
(SETQ z (CONS '(red white blue) (CDR '(This is a list)))) ((red white blue) is a list)
(REVERSE z) (list a is (red white blue))
(CDDAR z) (blue)

Arithmetic Functions (ADD, MULT, ...)

As you have probably already figured out, the function ADD simply summed its arguments. We'll also be using the following arithmetic functions:

Function Result
(ADD x1 x2 …) sum of all arguments
(SUB a b) a-b
(MULT x1 x2 …) product of all arguments
(DIV a b) a/b
(SQUARE a) a*a
(EXP a n) an
(EQ a b) true if a and b are equal, NIL otherwise
(POS a) true if a is positive, NIL otherwise
(NEG a) true if a is negative, NIL otherwise

Functions ADD, SUB, MULT, and DIV can be written as their common mathematical symbols, +, -, *, and /. Here are some examples of these functions:

Statement Value
(ADD (EXP 2 3) (SUB 4 1) (DIV 54 4)) 24.5
(- (* 3 2) (- 12 (+ 1 2 1))) -2
(ADD (SQUARE 3) (SQUARE 4)) 25

User-defined Functions

LISP also allows us to create our own functions using the DEF function. (We will sometimes use DEFUN rather than DEF, as it is a bit more standard terminology.) For example,

(DEF SECOND (args) (CAR (CDR args)))

defines a new function called SECOND which operates on a single parameter named "args". SECOND will take the CDR of the parameter and then the CAR of that result. So, for example: (SECOND '(a b c d e)) would first CDR the list to give (b c d e), and then CAR that value returning the single character "b". Consider the following program fragment:

(SETQ X '(a c s l))
(DEF WHAT(args) (CONS args (REVERSE (CDR args))))
(DEF SECOND(args) (CONS (CAR (CDR args)) NIL))

The following chart illustrates the use of the user-defined functions WHAT and SECOND:

Statement Value
(WHAT X) ((a c s l) l s c)
(SECOND X) (c)
(SECOND (WHAT X)) (l)
(WHAT (SECOND X)) ((c))

Online Interpreters

There are many online LISP interpreters available on the Internet. The one that ACSL uses for testing its programs is CLISP that is accessible from JDoodle. This interpreter is nice because it is quite peppy in running programs, and functions are not case sensitive. So, (CAR (CDR x)) is legal as is (car (cdr x)) One drawback of this interpreter is the print function changes lowercase input into uppercase.

Sample Problems

Questions from this topic will typically present a line of LISP code or a short sequence of statements and ask what is the value of the (final) statement.

Problem 1

Evaluate the following expression. (MULT (ADD 6 5 0) (MULT 5 1 2 2) (DIV 6 (SUB 2 5)))

Solution:

(MULT (ADD 6 5 0) (MULT 5 1 2 2) (DIV 6 (SUB 2 5)))
(MULT 11 20  (DIV 6 -3))
(MULT 11 20 -2)
-440

Problem 2

Evaluate the following expression: (CDR '((2 (3))(4 (5 6) 7)))

Solution: The CDR function takes the first element of its parameter (which is assumed to be a list) and returns the list with the first element removed. The first element of the list is (2 (3)) and the list without this element is ((4 (5 6) 7)), a list with one element.

Problem 3

Consider the following program fragment:

(SETQ X '(RI VA FL CA TX))
(CAR (CDR (REVERSE X)))

What is the value of the CAR expression?

Solution: The first statement binds variable X to the list '(RI VA FL CA TX). The REVERSE of this list is '(TX CA FL VA RI) whose CDR is '(CA FL VA RI). The CAR of this list is just the atom CA (without the quote).


Video Resources

The following YouTube videos show ACSL students and advisors working out some ACSL problems that have appeared in previous contests. Some of the videos contain ads; ACSL is not responsible for the ads and does not receive compensation in any form for those ads.

LISP very gentle intro (CalculusNguyenify)

A very gentle introduction to the LISP category, covering the LISP syntax and the basic operators, SETQ, ADD, SUB, MULT, and DIV.

LISP Basics (for ACSL) (Tangerine Code)

Explains the LISP operators CAR, CDR, and REVERSE, in the context of solving an ACSL All-Star Contest problem.

LISP Basics (for ACSL) (Tangerine Code)

Completes the problem that was started in the above video.