2.sld 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. ;;; 2.scm --- AND-LET*: an AND with local bindings, a guarded LET* special form
  2. ;; Copyright (C) 2014 Taylan Ulrich Bayırlı/Kammer
  3. ;; Author: Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
  4. ;; Keywords: srfi srfi-2 and-let and-let* and let let*
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU Lesser General Public License as
  7. ;; published by the Free Software Foundation, either version 3 of the
  8. ;; License, or (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU Lesser General Public License for more details.
  13. ;; You should have received a copy of the GNU Lesser General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; Implementing this is tricky because when there is no body, the last evaluated
  17. ;; clause should be returned, not #t, so we can't terminate our recursive macro
  18. ;; with a rule (and-let* () body ...) -> (and body ...), since that would mean
  19. ;; we're left with a dangling (and) i.e. #t. Additionally, the BOUND-VARIABLE
  20. ;; case should match identifiers only; we force it to fail on non-identifiers by
  21. ;; abusing `let', but are careful not to evaluate any expressions under this
  22. ;; let, since that changes the effect of `set!'.
  23. ;;
  24. ;; We break up from the specification of this SRFI in that we allow the same
  25. ;; variable to be bound multiple times in sequential clauses. The SRFI author
  26. ;; seems to have interpreted old RnRS versions as disallowing that in `let*'
  27. ;; when in fact it was ambiguous, and it's explicitly allowed starting from
  28. ;; R6RS. Racket's, Guile's, and Chibi's SRFI-2 implementations allow it too.
  29. ;; Also, this is simple to implement; the alternative seems either very hard or
  30. ;; impossible to implement with syntax-rules.
  31. ;;; Code:
  32. (define-library (srfi 2)
  33. (export and-let*)
  34. (import (scheme base))
  35. (begin
  36. (define-syntax and-let*
  37. (syntax-rules ()
  38. ((and-let* ((var expr) rest rest* ...) body ...)
  39. (let ((var expr))
  40. (and var (and-let* (rest rest* ...) body ...))))
  41. ((and-let* ((expr) rest rest* ...) body ...)
  42. (and expr (and-let* (rest rest* ...) body ...)))
  43. ((and-let* (bound-var rest rest* ...) body ...)
  44. (begin
  45. (let ((bound-var #f)) #f) ;(identifier? bound-var)
  46. (and bound-var (and-let* (rest rest* ...) body ...))))
  47. ((and-let* ((var expr)) body ...)
  48. (let ((var expr))
  49. (and var body ...)))
  50. ((and-let* ((expr)) body ...)
  51. (and expr body ...))
  52. ((and-let* (bound-var) body ...)
  53. (begin
  54. (let ((bound-var #f)) #f) ;(identifier? bound-var)
  55. (and bound-var body ...)))
  56. ((and-let* () body ...)
  57. (and body ...))))))
  58. ;;; 2.scm ends here