-
-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Concept Exercise: Lilly's Lasagna Leftovers
Also includes a first draft of a new concept: lambda-list
- Loading branch information
1 parent
f78821b
commit b1c5a48
Showing
17 changed files
with
445 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,21 @@ | ||
TODO: add information on default-parameters concept | ||
An optional parameter is designated by the `&optional` lambda list keyword in a lambda list. Optional parameters are not required, can have a default and also can specify a "supplied-p parameter" which will be "true" or "false" depending on whether an argument was provided for the parameter. | ||
|
||
```lisp | ||
(defun optional-parameter (&optional (arg -1)) arg) | ||
(optional-parameter) ;; => -1 | ||
(optional-parameter 13) ;; => 13 | ||
``` | ||
|
||
Optional parameters must be put after required parameters but before named or rest parameters. Arguments are first bound to required parameters, then optional parameters and finally to rest and named parameters. | ||
|
||
```lisp | ||
(defun req-and-opt (req &optional (opt -1)) (list req opt) | ||
(req-and-opt 1) ;; => (1 -1) | ||
(req-and-opt 1 13) ;; => (1 13) | ||
``` | ||
|
||
While multiple types of parameters can be combined with other types of parameters (optional and keyword arguments) this can be be problematic and should be done carefully. See the section on ("Mixing Different Parameter Types")(pcl-function) in Practical Common Lisp. | ||
|
||
-- | ||
|
||
[pcl-function]: http://www.gigamonkeys.com/book/functions.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,6 @@ | ||
[] | ||
[ | ||
{ | ||
"url": "http://www.gigamonkeys.com/book/functions.html", | ||
"description": "Practical Common Lisp chapter 5: Functions" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
In Common Lisp a parameter list (such as for defining a function) is also known as a (lambda list)[lambda-list]. Lambda lists are also used for defining macros and destructuring. | ||
|
||
Lambda lists can contain (lambda list keywords)[lambda-list-keyword] such as `&rest`, `&optional`, `&key` and others. | ||
|
||
While multiple types of parameters can be combined with other types of parameters (optional and keyword arguments) this can be be problematic and should be done carefully. See the section on ("Mixing Different Parameter Types")(pcl-function) in Practical Common Lisp. | ||
|
||
-- | ||
|
||
[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 | ||
[pcl-function]: http://www.gigamonkeys.com/book/functions.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[ | ||
{ | ||
"url": "http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list", | ||
"description": "Definition of Lambda List" | ||
}, | ||
{ | ||
"url": "http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lambda_list_keyword", | ||
"description": "Definition of Lambda List Keyword" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,22 @@ | ||
TODO: add information on named-parameters concept | ||
In Common Lisp named parameters are called keyword parameters. | ||
|
||
Keyword parameters are designated by the `&key` lambda list keyword in a lambda list. Keyword parameters are not required, can have a default and also can specify a "supplied-p parameter" which will be "true" or "false" depending on whether an argument was provided for the parameter. | ||
|
||
```lisp | ||
(defun keyword-parameter (&key (arg -1) arg) | ||
(keyword-parameter) ;; => -1 | ||
(keyword-parameter :arg 13) ;; => 13 | ||
``` | ||
|
||
In the arguments to a function the keyword parameters are specified by their "keyword name" which is, by default, a keyword symbol version of the parameter name (_i.e._ keyword parameter `name` has a keyword name of `:name`). It is possible to specify another name for the keyword parameter by using a list of keyword name and parameter name instead of just the parameter name: | ||
|
||
```lisp | ||
(defun other-keyword-name (&key ((other-name arg))) (list arg)) | ||
(other-keyword-name 'other-name 5) ;; => (5) | ||
``` | ||
|
||
While multiple types of parameters can be combined with other types of parameters (optional and keyword arguments) this can be be problematic and should be done carefully. See the section on ("Mixing Different Parameter Types")(pcl-function) in Practical Common Lisp. | ||
|
||
-- | ||
|
||
[pcl-function]: http://www.gigamonkeys.com/book/functions.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,6 @@ | ||
[] | ||
[ | ||
{ | ||
"url": "http://www.gigamonkeys.com/book/functions.html", | ||
"description": "Practical Common Lisp chapter 5: Functions" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
TODO: add information on rest-parameters concept | ||
A rest parameter is designated by the `&rest` lambda list keyword in a lambda list. This parameter will be bound to a value which is a list of all the arguments provided by the caller which is not consumed by other parameters. | ||
|
||
While multiple types of parameters can be combined with other types of parameters (optional and keyword arguments) this can be be problematic and should be done carefully. See the section on ("Mixing Different Parameter Types")(pcl-function) in Practical Common Lisp. | ||
|
||
-- | ||
|
||
[pcl-function]: http://www.gigamonkeys.com/book/functions.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,6 @@ | ||
[] | ||
[ | ||
{ | ||
"url": "http://www.gigamonkeys.com/book/functions.html", | ||
"description": "Practical Common Lisp chapter 5: Functions" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
## 1. Make `preparation-time-in-minutes` easier to use | ||
|
||
- A "rest parameter" will collect all arguments not consumed by other parameters into a list. | ||
- A "rest parameter" is designated in the lambda list with the `&rest` lambda list keyword. | ||
- The function `length` can be used to get the number of items in a list. | ||
|
||
## 2. Allow changing the expected oven time | ||
|
||
- An optional parameter can be provided or not. | ||
- An optional parameter can have a default value. | ||
- Optional parameters are designated by the `&optional` lambda list keyword. | ||
|
||
## 3. Lilly remembers another preferred cooking style | ||
|
||
- A "supplied-p parameter" can be specified with the optional parameter to determine if the caller has provided the parameter. | ||
|
||
## 4. Splitting the leftovers | ||
|
||
- Keyword parameters are named and are optional. | ||
- Keyword parameters are designated with the `&key` lambda list keyword. | ||
|
||
## 5. Making assumptions | ||
|
||
- Keyword parameters can have default values. | ||
|
||
## 6. Standard amount of leftovers | ||
|
||
- Keyword parameters can have a "supplied-p parameter" like optional parameters. |
110 changes: 110 additions & 0 deletions
110
exercises/concept/lillys-lasagna-leftovers/.docs/instructions.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
Lilly the Lisp Alien has definitely made a lot of Lasagna with your | ||
help. They want to thank you by giving you some leftovers. But first | ||
they have some feedback about one of the functions you helped them | ||
with. | ||
|
||
In this exercise you are going to write some more functions to help | ||
Lilly with their Lasagna cooking as well as helping them split the | ||
leftovers with you. | ||
|
||
You have six tasks, three about improving the existing Lasagna cooking | ||
functions and three about splitting the leftovers. | ||
|
||
## 1. Make `preparation-time-in-minutes` easier to use | ||
|
||
Lilly says they found using your `preparation-time-in-minutes` a | ||
little awkward to use since they had to count all the layers before | ||
using the functions. Lilly wonders if you could make a version of the | ||
function that takes the layers (any number of them) as arguments and | ||
then calculate the preparation time based upon how many layers there | ||
were? As a reminder, it takes 19 minutes to prepare a single layer. | ||
|
||
```lisp | ||
(preparation-time 'sauce 'cheese 'right-handed-macaroni 'cheese 'sauce | ||
'left-handed-macaroni 'sauce 'sauce 'cheese 'cheese) | ||
;; => 190 (because there are 10 layers.) | ||
``` | ||
|
||
## 2. Allow changing the expected oven time | ||
|
||
While Lilly's parental-units always cooked their lasagna for 337 | ||
minutes, Lilly does admit that other Lisp Aliens like to cook their | ||
lasagna for longer or shorter amounts of time. | ||
|
||
So it would be good if `remaining-minutes-in-oven` would not use | ||
`expected-minutes-in-oven` but instead could take an _optional_ | ||
parameter to define if the time should be longer, very long, shorter | ||
or very short. Longer or shorter means add or subtract 100 from the | ||
default time of 337. Very long or very short means add or | ||
subtract 200. If no parameter is provided, or the argument is 'normal' | ||
then the default value of 337 should be returned. | ||
|
||
```lisp | ||
(remaining-minutes-in-oven) ;; => 337 | ||
(remaining-minutes-in-oven :normal) ;; => 337 | ||
(remaining-minutes-in-oven :shorter) ;; => 237 | ||
(remaining-minutes-in-oven :longer) ;; => 437 | ||
(remaining-minutes-in-oven :very-long) ;; => 537 | ||
``` | ||
|
||
## 3. Lilly remembers another preferred cooking style | ||
|
||
Just after you finished that change Lilly remembers that there are | ||
some Lisp Aliens that like _really short_ cooking times. Effectively | ||
they want it raw. So now the function should return 0 if `NIL` was the | ||
argument as well as the same values as in the previous task. | ||
|
||
```lisp | ||
(remaining-minutes-in-oven) ;; => 337 | ||
(remaining-minutes-in-oven nil) ;; => 0 | ||
``` | ||
|
||
## 4. Splitting the leftovers | ||
|
||
Now that you've helped improve the lasagna cooking functions there is | ||
_a lot of lasanga_! Lilly wants to repay you for all your help by | ||
splitting the leftovers with you. You will need to write a function | ||
that takes three parameters: the total amount of leftovers, the number | ||
of containers for leftovers Lilly found in their cupboards and the | ||
same for you. Because searching for leftover containers may take | ||
different amounts of time, and the exact amount of leftovers may be | ||
determined while yourself and Lilly are out searching your cupboards | ||
you both agree that the function should take the arguments in any | ||
order, so as each number is determined you can write it down. When you | ||
have all three numbers you can just close the parenthesis on the | ||
function call and evaluate it. | ||
|
||
The function should return the amount of leftovers which are leftover, | ||
that is, the difference between the weight of left-overs and the total | ||
number of containers that you and Lilly found. | ||
|
||
```lisp | ||
(split-leftovers :weight 20 :human 10 :alien 5) ;; => 5 | ||
(split-leftovers :weight 20 :alien 10 :human 2) ;; => 8 | ||
(split-leftovers :alien 12 :weight 20 :human 4) ;; => 4 | ||
``` | ||
|
||
## 5. Making assumptions | ||
|
||
After a few trips back and forth to your respective cupboards, you | ||
both agree that it would be great if the function could just _assume_ | ||
that you or Lilly had... say 10 containers if it were not specified. | ||
|
||
```lisp | ||
(split-leftovers :weight 20 :human 5) ;; => 5 | ||
(split-leftovers :weight 20 :alien 5) ;; => 5 | ||
(split-leftovers :weight 20) ;; => 0 | ||
``` | ||
|
||
## 6. Standard amount of leftovers | ||
|
||
Even better the function could _assume_ that there is enough leftovers | ||
to fit into the containers. So if the weight is not provided the | ||
function should return `'just-split-it`. _However_ if the weight is | ||
provided and it is `nil` or `0` then it should return | ||
`'looks-like-someone-was-hungry`. | ||
|
||
```lisp | ||
(split-left-overs :human 5 :alien 5) ;; => :JUST-SPLIT-IT | ||
(split-left-overs :weight NIL :human 5 :alien 5) ;; => :LOOKS-LIKE-SOMEONE-WAS-HUNGRY | ||
``` |
53 changes: 53 additions & 0 deletions
53
exercises/concept/lillys-lasagna-leftovers/.docs/introduction.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
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 |
14 changes: 14 additions & 0 deletions
14
exercises/concept/lillys-lasagna-leftovers/.meta/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"authors": [ | ||
{ | ||
"github_username": "verdammelt", | ||
"exercism_username": "verdammelt" | ||
} | ||
], | ||
"contributors": [], | ||
"forked_from": ["swift/lasagna-master"], | ||
"editor": { | ||
"solution_files": ["lillys-lasagna-leftovers.lisp"], | ||
"test_files": ["lillys-lasagna-leftovers-test.lisp"] | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
exercises/concept/lillys-lasagna-leftovers/.meta/design.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
## Goal | ||
|
||
This exercise should focus on teaching about the special types of arguments to `defun`: `&key`, `&rest`, `&optional`. | ||
|
||
## Learning objectives | ||
|
||
- Know how to take optional arguments using `&optional` | ||
- Know how to use `&rest` to take an arbitrary number of arguments | ||
- Know how to take keyword arguments using `&key` | ||
- Know how to set default values for optional / keyword arguments | ||
- Be able to use `supplied-p` parameters with optional / keyword | ||
arguments | ||
|
||
## Out of scope | ||
|
||
- Anonymous functions using `lambda` | ||
- Local functions using `flet`, `labels`, etc. | ||
- Recursion / self-referential functions | ||
- The somewhat arcane `&aux` keyword | ||
- The `&allow-other-keys` keyword | ||
- Multiple value returns with `values` | ||
- Early returns with `return-from` | ||
- Methods / generic functions | ||
- Higher-order functions | ||
- Macros | ||
|
||
The concept file for `named-parameters` can (and perhaps should) mention `&allow-other-keys`. | ||
|
||
## Concepts | ||
|
||
- `named-parameters` | ||
- `rest-parameters` | ||
- `default-parameters` | ||
|
||
## Prerequisites | ||
|
||
- `functions` | ||
- `expressions` | ||
- `integers` | ||
- `arithmetic` | ||
- `conditionals` | ||
|
||
## Resources to refer to | ||
|
||
- [Practical Common | ||
Lisp](http://www.gigamonkeys.com/book/functions.html) | ||
- [Common Lisp Hyperspec](http://clhs.lisp.se/Body/m_defun.htm) | ||
|
||
### Hints | ||
|
||
- [Common Lisp | ||
Cookbook](https://lispcookbook.github.io/cl-cookbook/functions.html) |
Oops, something went wrong.