Skip to content

Commit

Permalink
Add concept introductions
Browse files Browse the repository at this point in the history
Add concept introductions, either stubs or initialized from the contents of the introductions from the related concept exercises.
  • Loading branch information
ErikSchierboom authored and TheLostLambda committed Jan 29, 2021
1 parent b1c5a48 commit 2064c59
Show file tree
Hide file tree
Showing 37 changed files with 367 additions and 0 deletions.
1 change: 1 addition & 0 deletions concepts/anonymous-functions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for anonymous-functions concept
14 changes: 14 additions & 0 deletions concepts/arithmetic/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Common Lisp uses the standard arithmetic operators for most operations but is
somewhat unique in using a "prefix-notation" as opposed to the more familiar
"infix-notion". More visually:

```lisp
;; Infix-notation (non-lisp languages)
1 + 2 + 3 + 4 + 5 ; => 15
;; Prefix-notation (lisp languages)
(+ 1 2 3 4 5) ; => 15
```

While prefix notion turns some operations like `2 + 2` into the somewhat
unfamiliar `(+ 2 2)` form, it makes it much easier to operate on more than one
number at a time.
1 change: 1 addition & 0 deletions concepts/arrays/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for arrays concept
1 change: 1 addition & 0 deletions concepts/assignment/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for assignment concept
1 change: 1 addition & 0 deletions concepts/characters/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for characters concept
1 change: 1 addition & 0 deletions concepts/code-as-data/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for code-as-data concept
10 changes: 10 additions & 0 deletions concepts/comments/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Common Lisp allows the programmer to write "comments" that are ignored by the
computer. Single-line comments begin with one or more semi-colons (`;`) and,
occasionally, you may see the following:

```lisp
(code...) ; => value
```

Where the comment is being used to indicate what value is returned by Common
Lisp after running the code on that line.
36 changes: 36 additions & 0 deletions concepts/conditionals/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Common lisp provides several different conditional expressions, the main difference being the number of branches they support.

- `when` and `unless` allow for a single branch:

```lisp
(when (= 2 2) "All is well") ; => "All is well"
(unless (= 2 2) "Time to panic!") ; => NIL
```

- `if` provides the classic if-then-else construct:

```lisp
(if (= 2 2) 'how-honest 'you-liar) ; => HOW-HONEST
```

- `cond` provides a way to have multiple branches without nesting `if` expressions:

```lisp
(cond ((= 0 2) 'nope)
((= 1 2) 'try-again)
((= 2 2) 'quite-true)
((= 3 2) 'too-far)
(t 'something-else))
; => QUITE-TRUE
```

- `case` provides a classic 'switch' style construct: It checks a single value against a number of branches:

```lisp
(case 'elder-beast
(cat "Meow")
(bird "Chirp")
(dog "Bark")
(otherwise "???"))
; => "???"
```
11 changes: 11 additions & 0 deletions concepts/cons/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
All Common Lisp code is either an "atom" (a single, indivisible value) or a list
(also termed a "cons"). A cons is made up of two parts: the first element and
the rest of the elements. For historical reasons these two parts are called the
`car` and the `cdr`. When these conses are evaluated as code, the first element
(`car`) represents the function being called while the rest of the elements
(`cdr`) represent the arguments to that function:

```lisp
(<function> <arg1> <arg2> ... <argN>)
; ^ car ^ | ^ cdr ^
```
1 change: 1 addition & 0 deletions concepts/constants/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for constants concept
10 changes: 10 additions & 0 deletions concepts/default-parameters/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
In Common Lisp a function can have some arguments are are optional. These are designated in the lambda list by `&optional` lambda list keyword. A parameter will be bound to the value `nil` if it is not specified. If there are several optional parameters they are bound in order. Default values can be specified for optional parameters. Finally a symbol an be specified for each optional parameter which will be bound to true or false depending on whether that parameter was supplied by the caller of the function (this is referred to as the "supplied-p parameter").

```lisp
(defun default-parameters (&optional x (y 'default) (z nil z-supplied-p))
(list x y (if z-supplied-p (list :z-was-supplied z)
(list :z-was-not-supplied z))))
(default-parameters) ;; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(default-parameters 5 nil 10) ;; => (5 NIL (:Z-WAS-SUPPLIED 10))
```
1 change: 1 addition & 0 deletions concepts/destructuring-assignment/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for destructuring-assignment concept
1 change: 1 addition & 0 deletions concepts/enumeration/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for enumeration concept
12 changes: 12 additions & 0 deletions concepts/expressions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Together, the atoms and conses that make up Lisp code are referred to as
S-Expressions (or sexpr for short). When S-Expressions are evaluated, they
automatically return some value which takes the place of the expression. When
writing your own functions (using `defun`), the last value within the body of
the `defun` is automatically returned:

```lisp
;; Defining a new function
(defun gimme-foo () 'foo)
;; Calling the function as an S-Expression
(gimme-foo) ; => FOO
```
1 change: 1 addition & 0 deletions concepts/floating-point-numbers/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Also like many languages, Common Lisp contains floating point numbers. These are fractional or whole numbers including a decimal point (like `3.14`, `-1.7`, `99.99`, `2048.0`)
49 changes: 49 additions & 0 deletions concepts/functions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
To define a global function in Common Lisp one uses the `defun`
expression. This expression takes as its first argument a list of
parameters (and empty list means the function has no parameters). This
is followed by an optional documentation string (see below), then zero
or more expressions which make up the "body" of the function.

Functions may have zero or more parameters.

```lisp
(defun no-args () (+ 1 1))
(defun add-one (x) (+1 x))
(defun add-nums (x y) (+ x y))
```

Calling a function is done by evaluating an expression with the symbol
designating the function as the first element of the expression with
the arguments to the function (if any) as the remaining items in the
expression.

The value that a function evaluates to is the value of the last
expression in the function body that was evaluated. All functions
evaluate to a value.

```lisp
(add-nums 2 2) ;; => 4
```

Functions can also have, optionally, a documentation string (also
called a 'docstring'). If provided it comes after the argument list
but before the body of the function. The documentation string can be
accessed via `documentation`.

```lisp
(defun add-nums (x y) "Add X and Y together" (+ x y))
(documentation 'add-nums 'function) ;; => "Add X and Y together"
;; Note that if one provides a docstring but fails to provide a body
;; then the docstring is interpreted by Common Lisp as the body, not
;; the docstring
(defun no-body ())
(no-body) ;; => NIL
(defun mistake () "This is not a docstring")
(mistake) ;; => "This is not a docstring"
(documentation 'mistake 'function) ;; => NIL
```
1 change: 1 addition & 0 deletions concepts/hash-tables/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for hash-tables concept
1 change: 1 addition & 0 deletions concepts/higher-order-functions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for higher-order-functions concept
8 changes: 8 additions & 0 deletions concepts/integers/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Like many languages Common Lisp contains integers. These are whole numbers without a decimal point (like `-6`, `0`, `25`, `1234`,
etc.)

Common Lisp defines no limits on the magnitude of integers. Integers can be arbitrarily large (or small if negative).

In general, if you are working with only whole numbers, you should prefer
integers as they don't suffer from the same loss of precision as floating-point
numbers do over many calculations.
55 changes: 55 additions & 0 deletions concepts/lambda-list/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
TODO: the content below is copied from the exercise introduction and probably needs rewriting to a proper concept introduction

In Common Lisp a functions argument list (also known as a ('lambda list')[lambda-list]) can have arguments of different types. These different types are designated with the use of ("lambda list keywords")[lambda-list-keyword] which all begin with `&`. The most commonly used types are optional, keyword and rest arguments types. Every parameter in the lambda list after a particular lambda list keyword is will be of that type. A lambda list keyword can only be used once in a lambda list.

## default-parameters

In Common Lisp a function can have some arguments are are optional. These are designated in the lambda list by `&optional` lambda list keyword. A parameter will be bound to the value `nil` if it is not specified. If there are several optional parameters they are bound in order. Default values can be specified for optional parameters. Finally a symbol an be specified for each optional parameter which will be bound to true or false depending on whether that parameter was supplied by the caller of the function (this is referred to as the "supplied-p parameter").

```lisp
(defun default-parameters (&optional x (y 'default) (z nil z-supplied-p))
(list x y (if z-supplied-p (list :z-was-supplied z)
(list :z-was-not-supplied z))))
(default-parameters) ;; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(default-parameters 5 nil 10) ;; => (5 NIL (:Z-WAS-SUPPLIED 10))
```

## named-parameters

In Common Lisp a function can have named parameters (referred to as "keyword parameters" or "keyword arguments"). These are designated in the lambda list by the `&key` lambda list keyword. Keyword parameters are not required parameters. Like optional parameters they can be given default values and symbols to bind to their 'supplied-or-not' state.

When calling a function with keyword parameters the name of the parameter as a keyword is used in front of the parameter value. Keyword parameters can be specified by the caller of the function in any order.

```lisp
(defun keyword-parameters (&key x (y 'default) (z nil z-supplied-p))
(list x y (if z-supplied-p (list :z-was-supplied z)
(list :z-was-not-supplied z))))
(keyword-parameters) ;; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :y 5) ;; => (NIL 5 (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :z 10 :x 5) ;; => (5 NIL (:Z-WAS-SUPPLIED 10))
```

Care should be taken when combining optional and keyword arguments as the keyword name and argument could be consumed by optional parameters:

```lisp
(defun could-be-confusing (&optional x y &key z) (list x y z))
(could-be-confusing :z 'huh?) ;; => (:Z HUH? NIL)
```

## rest-parameters

In Common Lisp a function can have a parameter that will contain the "rest" of the arguments after any required or optional parameters are processed. This parameter is designated by the `&rest` lambda list keyword. If all arguments to a function are used by by other types of parameters then the rest parameter will be bound to an empty list. If there are unused arguments then the rest parameter will be bound to a list of those arguments.

```lisp
(defun rest-of-it (req &optional opt &rest rest) (list req opt rest))
(rest-of-it 1) ;; => (1 NIL NIL)
(rest-of-it 1 2) ;; => (1 2 NIL)
(rest-of-it 1 2 3) ;; => (1 2 (3))
(rest-of-it 1 2 3 4 5) ;; => (1 2 (3 4 5))
```

--
[lambda-list]: http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list
[lambda-list-keyword]: http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list_keyword
43 changes: 43 additions & 0 deletions concepts/lists/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Given that the name of the language is Lisp which stands of _LISt Processing_ one might assume that the language has facilities for handling lists of items, and you'd be correct!

While Common Lisp has other data structures as well as lists, lists are still heavily used.

A list in Common Lisp is a sequence of items. The items themselves do not have to be the same type. For example you can have a list of `1`, `two`, `"III"`.

#### Creating Lists

One can simply type in a quoted list like this: `'(1 two "III")` and that will cause a list to be created and evaluated (it evaluates to: `(1 two "III")`.

There are also two main functions used to create lists: `list` and `cons`.

`list` takes zero or more arguments and evaluates to a list created with those values:

```lisp
(list 1 'two "III") ; => (1 two "III")
```

`cons` takes two items and creates a list which has as its `car` the first item and as its `cdr` the second item:

```lisp
(cons 1 2) ; => (1 . 2) ;; (a list without `nil` as its `cdr` is printed in this way.)
(cons 1 nil) ; => (1)
(cons 1 (cons 2 nil)) ; => (1 2)
```

`car` and `cdr` can be used to access the `car` and `cdr` respectively.

(`first` and `rest` are synonyms of `car` and `cdr` and work exactly the same.)

#### Length & Random Access

The length of a list can be determined by the use of `length`. An empty list has length zero.

An arbitrary item can be accessed with `nth` (note that lists are zero-indexed).

It is _not_ an error to request an index that is more than the length. Instead it evaluates to `nil`:

```lisp
(nth 23 '(short list))` ; => nil
```

There are also 10 helper methods for accessing the first 10 items of a list, they are named: `first`, `second`, `third`, `fourth`, `fifth`, `sixth`, `seventh`, `eighth`, `ninth`, and `tenth`.
1 change: 1 addition & 0 deletions concepts/loop.basic/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for loop.basic concept
1 change: 1 addition & 0 deletions concepts/multiple-values/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for multiple-values concept
20 changes: 20 additions & 0 deletions concepts/named-parameters/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
In Common Lisp a function can have named parameters (referred to as "keyword parameters" or "keyword arguments"). These are designated in the lambda list by the `&key` lambda list keyword. Keyword parameters are not required parameters. Like optional parameters they can be given default values and symbols to bind to their 'supplied-or-not' state.

When calling a function with keyword parameters the name of the parameter as a keyword is used in front of the parameter value. Keyword parameters can be specified by the caller of the function in any order.

```lisp
(defun keyword-parameters (&key x (y 'default) (z nil z-supplied-p))
(list x y (if z-supplied-p (list :z-was-supplied z)
(list :z-was-not-supplied z))))
(keyword-parameters) ;; => (NIL DEFAULT (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :y 5) ;; => (NIL 5 (:Z-WAS-NOT-SUPPLIED NIL))
(keyword-parameters :z 10 :x 5) ;; => (5 NIL (:Z-WAS-SUPPLIED 10))
```

Care should be taken when combining optional and keyword arguments as the keyword name and argument could be consumed by optional parameters:

```lisp
(defun could-be-confusing (&optional x y &key z) (list x y z))
(could-be-confusing :z 'huh?) ;; => (:Z HUH? NIL)
```
1 change: 1 addition & 0 deletions concepts/nested-functions/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for nested-functions concept
1 change: 1 addition & 0 deletions concepts/packages/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for packages concept
1 change: 1 addition & 0 deletions concepts/printing/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for printing concept
1 change: 1 addition & 0 deletions concepts/recursion/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for recursion concept
13 changes: 13 additions & 0 deletions concepts/rest-parameters/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
In Common Lisp a function can have a parameter that will contain the "rest" of the arguments after any required or optional parameters are processed. This parameter is designated by the `&rest` lambda list keyword. If all arguments to a function are used by by other types of parameters then the rest parameter will be bound to an empty list. If there are unused arguments then the rest parameter will be bound to a list of those arguments.

```lisp
(defun rest-of-it (req &optional opt &rest rest) (list req opt rest))
(rest-of-it 1) ;; => (1 NIL NIL)
(rest-of-it 1 2) ;; => (1 2 NIL)
(rest-of-it 1 2 3) ;; => (1 2 (3))
(rest-of-it 1 2 3 4 5) ;; => (1 2 (3 4 5))
```

--
[lambda-list]: http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list
[lambda-list-keyword]: http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list_keyword
33 changes: 33 additions & 0 deletions concepts/sameness/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Common Lisp has many different equality predicates. This differs from other programming languages which may have only one or two (perhaps `==` and `===` for example). Some of these predicates in Common Lisp are specific to types, while others are generic. It is these latter that this exercise will teach.

There are four generic equality predicates and they differ by their restrictiveness on what they consider "equal". They are, in order from most restrictive to least restrictive: `eq`, `eql`, `equal`, and `equalp`.

A quick set of definitions (leaving out a few details) are as follows:

- `eq`: defines equality as meaning the two objects are identical.
_e.g._:

- `(eq 'a 'a) ; => T`
- `(eq (list 1 2) (list 1 2)) ; => NIL`

- `eql`: defines equality as meaning two numbers with the same type and value, two characters which are the same,
or for anything else if they are `eq`.
_e.g._:

- `(eql 1 1) ; => T`
- `(eql #\a #\a) ; => T`
- `(eql 1 1.0) ; => NIL`
- `(eql #\a #\A) ; => NIL`

- `equal`: defines equality as meaning: two lists are `equal` if each element is also `equal`; two arrays are `equal` if each element is `eq`; two strings are `equal` if each element is `eql`; everything else is `equal` if they are `eql`.
_e.g._:

- `(equal (list 1 2) (list 1 2)) ; => T`
- `(equal #(1 2) #(1 2)) ; => T`
- `(equal "foo" "foo") ; => T`

- `equalp`: defines equality as meaning: strings and characters are compared in a case-insensitive manner; numbers are compared with some type conversion; lists and arrays are `equalp` if every element is also `equalp`, structures if they are the same type and all slots are `equalp` and hash-tables if their keys and values are `equalp`
_e.g._:
- `(equal "foo" "FoO") ; => T`
- `(equal 3 3.0) ; => T`
- `(equal (make-a-structure :slot1 1 :slot2 2) (make-a-structure :slot1 1 :slot2 2)) ; => T`
1 change: 1 addition & 0 deletions concepts/scope/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for scope concept
1 change: 1 addition & 0 deletions concepts/sets/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for sets concept
1 change: 1 addition & 0 deletions concepts/strings/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for strings concept
1 change: 1 addition & 0 deletions concepts/structures/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: add introduction for structures concept
30 changes: 30 additions & 0 deletions concepts/symbols/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
There are a couple of things to note regarding the example above. Firstly, the
_symbol_ `FOO` is an atom, as it only has one "part" (unlike a cons which has
two). Additionally, Common Lisp is **case-insensitive**, so symbols are often
returned as all uppercase, but `foo`, `Foo` and `FOO` are equivalent.

Symbols in Lisp are special values that can point to other values or, in the
case of _keywords_, themselves. When symbols are evaluated by Lisp, they are
replaced with the values they point to:

```lisp
foo ; => <whatever-foo-points-to>
:foo ; => :FOO
```

Note that keywords are denoted by a leading colon (`:`).

Quoting – the addition of `'` before an S-expression – tells Lisp to not
evaluate that expression. By quoting `'foo` in our `defun` example, we avoided
Lisp attempting to look up (and failing to find) whatever `FOO` was supposed to
point to, instead, returning the value `FOO` itself. If `FOO` has not been
defined anywhere in our program:

```lisp
foo ; => <ERROR! Lisp doesn't know what foo points to!>
'foo ; => FOO
```

For now, you can consider this just as a way to return symbols from a function,
but we will revisit quoting and further explore its implications in future
concept exercises.
Loading

0 comments on commit 2064c59

Please sign in to comment.