Fork of https://github.com/google/lisp-koans so that I could go through them. THIS CONTAINS ANSWERS.

structures.lsp 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. ;; Copyright 2013 Google Inc.
  2. ;;
  3. ;; Licensed under the Apache License, Version 2.0 (the "License");
  4. ;; you may not use this file except in compliance with the License.
  5. ;; You may obtain a copy of the License at
  6. ;;
  7. ;; http://www.apache.org/licenses/LICENSE-2.0
  8. ;;
  9. ;; Unless required by applicable law or agreed to in writing, software
  10. ;; distributed under the License is distributed on an "AS IS" BASIS,
  11. ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. ;; See the License for the specific language governing permissions and
  13. ;; limitations under the License.
  14. ;; Lisp structures encapsulate data which belongs together. They are
  15. ;; a template of sorts, providing a way to generate multiple instances of
  16. ;; uniformly organized information
  17. ;;
  18. ;; Defining a struct also interns accessor functions to get and set the fields
  19. ;; of the structure.
  20. ;; Define a new struct with the defstruct form. The following call creates a
  21. ;; new structure type named basketball-player, with slots named:
  22. ;; 'name', 'team', and number.
  23. (defstruct basketball-player name team number)
  24. (define-test test-make-struct
  25. ;; Create a basketball structure instance, and then read out the values.
  26. (let ((player-1 (make-basketball-player
  27. :name "larry" :team :celtics :number 33)))
  28. (assert-equal "larry" (basketball-player-name player-1))
  29. (assert-equal :celtics (basketball-player-team player-1))
  30. (assert-equal 33 (basketball-player-number player-1))
  31. (assert-equal 'basketball-player (type-of player-1))
  32. (setf (basketball-player-team player-1) :RETIRED)
  33. (assert-equal :RETIRED (basketball-player-team player-1))))
  34. ;; Struct fields can have default values
  35. ;; fields without explicit defaults default to nil.
  36. (defstruct baseball-player name (position :outfield) (team :red-sox))
  37. (define-test test-struct-defaults
  38. (let ((player-2 (make-baseball-player)))
  39. (assert-equal :outfield (baseball-player-position player-2))
  40. (assert-equal :red-sox (baseball-player-team player-2))
  41. (assert-equal nil (baseball-player-name player-2))))
  42. ;; The accessor names can get pretty long. It's possible to specify
  43. ;; a nickname to make code readable with the :conc-name option.
  44. (defstruct (american-football-player (:conc-name nfl-guy-)) name position team)
  45. (define-test test-abbreviated-struct-access
  46. (let ((player-3 (make-american-football-player
  47. :name "Drew Brees" :position :QB :team "Saints")))
  48. (assert-equal :QB (nfl-guy-position player-3))))
  49. ;; Structs can be defined as EXTENSIONS to previous structures.
  50. ;; This form of inheritance allows composition of objects.
  51. (defstruct (nba-contract (:include basketball-player)) salary start-year end-year)
  52. (define-test test-structure-extension
  53. (let ((contract-1 (make-nba-contract
  54. :salary 136000000
  55. :start-year 2004
  56. :end-year 2011
  57. :name "Kobe Bryant"
  58. :team :LAKERS
  59. :number 24)))
  60. (assert-equal 2004 (nba-contract-start-year contract-1))
  61. (assert-equal 'NBA-CONTRACT (type-of contract-1))
  62. ;; do inherited structures follow the rules of type hierarchy?
  63. (true-or-false? t (typep contract-1 'BASKETBALL-PLAYER))
  64. ;; can you access structure fields with the inherited accessors?
  65. (assert-equal :LAKERS (nba-contract-team contract-1))
  66. (assert-equal :LAKERS (basketball-player-team contract-1))))
  67. ;; Copying of structs is handled with the copy-{name} form. Note that
  68. ;; copying is shallow.
  69. (define-test test-structure-copying
  70. (let ((manning-1 (make-american-football-player :name "Manning" :team '("Colts" "Broncos")))
  71. (manning-2 (make-american-football-player :name "Manning" :team '("Colts" "Broncos"))))
  72. ;; manning-1 and manning-2 are different objects
  73. (true-or-false? nil (eq manning-1 manning-2))
  74. ;; but manning-1 and manning-2 contain the same information
  75. ;; (note the equalp instead of eq
  76. (true-or-false? t (equalp manning-1 manning-2))
  77. ;; copied structs are much the same.
  78. (true-or-false? t (equalp manning-1 (copy-american-football-player manning-1)))
  79. (true-or-false? nil (eq manning-1 (copy-american-football-player manning-1)))
  80. ;; note that the copying is shallow
  81. (let ((shallow-copy (copy-american-football-player manning-1)))
  82. (setf (car (nfl-guy-team manning-1)) "Giants")
  83. (assert-equal "Giants" (car (nfl-guy-team manning-1)))
  84. (assert-equal "Giants" (car (nfl-guy-team shallow-copy))))))