Skip to content

Commit

Permalink
Some more fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
phoe committed May 7, 2020
1 parent 0aee439 commit 36deb21
Show file tree
Hide file tree
Showing 8 changed files with 578 additions and 623 deletions.
4 changes: 2 additions & 2 deletions .koans
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
#:iteration
#:mapcar-and-reduce
#:control-statements
#:condition-handlers
#:loops
#:triangle-project
#:scoring-project
#:format
#:type-checking
#:clos
#:std-method-comb
#:condition-handlers
#:triangle-project
#:dice-project
#:macros
#:scope-and-extent
Expand Down
124 changes: 61 additions & 63 deletions koans/control-statements.lisp
Original file line number Diff line number Diff line change
@@ -1,70 +1,68 @@
;; Copyright 2013 Google Inc.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.
;;; Copyright 2013 Google Inc.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;; http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

;; TODO return-from

(define-test test-if-then-else
(define-test if
;; IF only evaluates and returns one branch of a conditional expression.
(assert-equal ____ (if t :true :false))
(assert-equal ____ (if nil :true :false))
;; This also applies to side effects that migh or might not be evaluated.
(let ((result))
(if t
(setf result "true value")
(setf result "false value"))
(assert-equal result ____)
(setf result :true)
(setf result :false))
(assert-equal ____ result)
(if nil
(setf result "true value")
(setf result "false value"))
(assert-equal result ____)))


(define-test test-when-and-unless
(let ((result-1 nil)
(result-2 nil)
(when-nums nil)
(unless-nums nil))
(dolist (x '(1 2 3 4 5 6 7 8 9 10))
(when (> x 5)
(setf result-1 x)
(push x when-nums))
(unless (> x 5)
(setf result-2 x)
(push x unless-nums)))
(assert-equal result-1 ___)
(assert-equal result-2 ___)
(assert-equal when-nums ___)
(assert-equal unless-nums ___)))

(setf result :true)
(setf result :false))
(assert-equal ____ result)))

(define-test test-and-short-circuits
"and only evaluates forms until one evaluates to nil"
(assert-equal
____
(let ((x 0))
(and
(setf x (+ 1 x))
(setf x (+ 1 x))
nil ;; <- ends execution of and.
(setf x (+ 1 x)))
x)))
(define-test when-unless
;; WHEN and UNLESS are like one-branched IF statements.
(let ((when-result nil)
(when-numbers '())
(unless-result nil)
(unless-numbers '()))
(dolist (x '(1 2 3 4 5 6 7 8 9 10))
(when (> x 5)
(setf when-result x)
(push x when-numbers))
(unless (> x 5)
(setf unless-result x)
(push x unless-numbers)))
(assert-equal ____ when-result)
(assert-equal ____ when-numbers)
(assert-equal ____ unless-result)
(assert-equal ____ unless-numbers)))

(define-test and-short-circuit
;; AND only evaluates forms until one evaluates to NIL.
(assert-equal ____
(let ((x 0))
(and
(setf x (+ 1 x))
(setf x (+ 1 x))
nil
(setf x (+ 1 x)))
x)))

(define-test test-or-also-short-circuits
"or only evaluates until one argument evaluates to non-nil"
(assert-equal
____
(let ((x 0))
(or
(setf x (+ 1 x))
(setf x (+ 1 x))
nil
(setf x (+ 1 x)))
x)))
(define-test or-short-circuit
;; AND only evaluates forms until one evaluates to non-NIL.
(assert-equal ____
(let ((x 0))
(or
(setf x (+ 1 x))
(setf x (+ 1 x))
nil
(setf x (+ 1 x)))
x)))
140 changes: 84 additions & 56 deletions koans/format.lisp
Original file line number Diff line number Diff line change
@@ -1,56 +1,84 @@
;; Copyright 2013 Google Inc.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.


;; FORMAT is lisp's counterpart to the c function printf. Refer to
;; http://www.gigamonkeys.com/book/a-few-format-recipes.html for more
;; on this topic.


;; FORMAT takes two fixed parameters. The first one specifies an
;; output stream that the result goes to, and if left as nil, FORMAT
;; will return the output as a string instead. The second parameter
;; specifies the format, where format specifier will be replaced by
;; formatting the rest of the parameters.

(define-test test-format-with-plain-text
"If there is no format specifier, FORMAT just returns the string
itself."
(assert-equal ___ (format nil "this is plain text.")))

(define-test test-format-with-general-specifier
"~a is a general specifier that translates to the print form of a
parameter."
(assert-equal ___ (format nil "~a" 42))
(assert-equal ___ (format nil "~a" #\C))
(assert-equal ___ (format nil "~a" "galaxy far far away"))
;; ~a can also translate to list
;; and parameters to FORMAT are passed by value
(assert-equal ___
(format nil "~a evaluates to ~a"
'(/ 8 (- 3 (/ 8 3)))
(/ 8 (- 3 (/ 8 3))))))

(define-test some-fancy-specifiers
"format enclosed by ~{ and ~} applies to every element in a list."
(assert-equal ___
(format nil "~{[~a]~}" '(1 2 3 4)))
;; ~^ within the ~{ ~} stops processing the last element in the list.
(assert-equal "1|2|3|4|" (format nil ___ '(1 2 3 4)))
(assert-equal ___ (format nil "~{~a~^|~}" '(1 2 3 4)))
;; ~r reads the integer
(assert-equal ___ (format nil "~r" 42))
;; put them all together
(assert-equal ___
(format nil "~{~r~^,~}" '(1 2 3 4))))
;;; Copyright 2013 Google Inc.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;; http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

;;; The function FORMAT is used to create formatted output. It is similar to
;;; the C function printf().
;;; See http://www.gigamonkeys.com/book/a-few-format-recipes.html

;;; T as the first argument to FORMAT prints the string to standard output.
;;; NIL as the first argument to FORMAT causes it to return the string.

(define-test format-basic
;; If there are no format directives in the string, FORMAT will return
;; a string that is STRING= to its format control.
(assert-equal ____ (format nil "Lorem ipsum dolor sit amet")))

(define-test format-aesthetic
;; The ~A format directive creates aesthetic output.
(assert-equal ____ (format nil "This is the number ~A" 42))
(assert-equal ____ (format nil "This is the keyword ~A" :foo))
(assert-equal ____ (format nil "~A evaluates to ~A"
'(/ 24 (- 3 (/ 8 3)))
(/ 24 (- 3 (/ 8 3)))))
(assert-equal ____ (format nil "This is the character ~A" #\C))
(assert-equal ____ (format nil "In a ~A" "galaxy far far away")))

(define-test format-standard
;; The ~S format directive prints objects with escape characters.
;; Not all Lisp objects require to be escaped.
(assert-equal ____ (format nil "This is the number ~S" 42))
(assert-equal ____ (format nil "~S evaluates to ~S"
'(/ 24 (- 3 (/ 8 3)))
(/ 24 (- 3 (/ 8 3)))))
;; Keywords are printed with their leading colon.
(assert-equal ____ (format nil "This is the keyword ~S" :foo))
;; Characters are printed in their #\X form. The backslash will need to be
;; escaped inside the printed string, just like in "#\\X".
(assert-equal ____ (format nil "This is the character ~S" #\C))
;; Strings include quote characters, which must be escaped:
;; such a string might look in code like "foo \"bar\"".
(assert-equal ____ (format nil "In a ~S" "galaxy far far away")))

(define-test format-radix
;; The ~B, ~O, ~D, and ~X radices print numbers in binary, octal, decimal, and
;; hexadecimal notation.
(assert-equal ____ (format nil "This is the number ~B" 42))
(assert-equal ____ (format nil "This is the number ~O" 42))
(assert-equal ____ (format nil "This is the number ~D" 42))
(assert-equal ____ (format nil "This is the number ~X" 42))
;; We can specify a custom radix by using the ~R directive.
(assert-equal ____ (format nil "This is the number ~3R" 42))
;; It is possible to print whole forms this way.
(let ((form '(/ 24 (- 3 (/ 8 3))))
(result (/ 24 (- 3 (/ 8 3)))))
(assert-equal ____ (format nil "~B evaluates to ~B" form result))
(assert-equal ____ (format nil "~O evaluates to ~O" form result))
(assert-equal ____ (format nil "~D evaluates to ~D" form result))
(assert-equal ____ (format nil "~X evaluates to ~X" form result))
(assert-equal ____ (format nil "~3R evaluates to ~3R" form result))))

(define-test format-iteration
;; The ~{ and ~} directives iterate over a list.
(assert-equal ____ (format nil "~{[~A]~}" '(1 2 3 4 5 6)))
(assert-equal ____ (format nil "~{[~A ~A]~}" '(1 2 3 4 5 6)))
;; The directive ~^ aborts iteration when no more elements remain.
(assert-equal ____ (format nil "~{[~A]~^, ~}" '(1 2 3 4 5 6))))

(define-test format-case
;; The ~( and ~) directives adjust the string case.
(assert-equal ____ (format nil "~(~A~)" "The QuIcK BROWN fox"))
;; Some FORMAT directives can be further adjusted with the : and @ modifiers.
(assert-equal ____ (format nil "~:(~A~)" "The QuIcK BROWN fox"))
(assert-equal ____ (format nil "~@(~A~)" "The QuIcK BROWN fox"))
(assert-equal ____ (format nil "~:@(~A~)" "The QuIcK BROWN fox")))
Loading

0 comments on commit 36deb21

Please sign in to comment.