poe.scm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. ;;; installed-scm-file
  2. ;;;; Copyright (C) 1996, 2001, 2006, 2011 Free Software Foundation, Inc.
  3. ;;;;
  4. ;;;; This library is free software; you can redistribute it and/or
  5. ;;;; modify it under the terms of the GNU Lesser General Public
  6. ;;;; License as published by the Free Software Foundation; either
  7. ;;;; version 3 of the License, or (at your option) any later version.
  8. ;;;;
  9. ;;;; This library 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 GNU
  12. ;;;; Lesser General Public License for more details.
  13. ;;;;
  14. ;;;; You should have received a copy of the GNU Lesser General Public
  15. ;;;; License along with this library; if not, write to the Free Software
  16. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;;;
  18. (define-module (ice-9 poe)
  19. :use-module (ice-9 hcons)
  20. :export (pure-funcq perfect-funcq))
  21. ;;; {Pure Functions}
  22. ;;;
  23. ;;; A pure function (of some sort) is characterized by two equality
  24. ;;; relations: one on argument lists and one on return values.
  25. ;;; A pure function is one that when applied to equal arguments lists
  26. ;;; yields equal results.
  27. ;;;
  28. ;;; If the equality relationship on return values can be eq?, it may make
  29. ;;; sense to cache values returned by the function. Choosing the right
  30. ;;; equality relation on arguments is tricky.
  31. ;;;
  32. ;;; {pure-funcq}
  33. ;;;
  34. ;;; The simplest case of pure functions are those in which results
  35. ;;; are only certainly eq? if all of the arguments are. These functions
  36. ;;; are called "pure-funcq", for obvious reasons.
  37. ;;;
  38. (define funcq-memo (make-weak-key-hash-table 523)) ; !!! randomly selected values
  39. (define funcq-buffer (make-gc-buffer 256))
  40. (define (funcq-hash arg-list n)
  41. (let ((it (let loop ((x 0)
  42. (arg-list arg-list))
  43. (if (null? arg-list)
  44. (modulo x n)
  45. (loop (logior x (hashq (car arg-list) 4194303))
  46. (cdr arg-list))))))
  47. it))
  48. ;; return true if lists X and Y are the same length and each element is `eq?'
  49. (define (eq?-list x y)
  50. (if (null? x)
  51. (null? y)
  52. (and (not (null? y))
  53. (eq? (car x) (car y))
  54. (eq?-list (cdr x) (cdr y)))))
  55. (define (funcq-assoc arg-list alist)
  56. (if (null? alist)
  57. #f
  58. (if (eq?-list arg-list (caar alist))
  59. (car alist)
  60. (funcq-assoc arg-list (cdr alist)))))
  61. (define not-found (list 'not-found))
  62. (define (pure-funcq base-func)
  63. (lambda args
  64. (let* ((key (cons base-func args))
  65. (cached (hashx-ref funcq-hash funcq-assoc funcq-memo key not-found)))
  66. (if (not (eq? cached not-found))
  67. (begin
  68. (funcq-buffer key)
  69. cached)
  70. (let ((val (apply base-func args)))
  71. (funcq-buffer key)
  72. (hashx-set! funcq-hash funcq-assoc funcq-memo key val)
  73. val)))))
  74. ;;; {Perfect funq}
  75. ;;;
  76. ;;; A pure funq may sometimes forget its past but a perfect
  77. ;;; funcq never does.
  78. ;;;
  79. (define (perfect-funcq size base-func)
  80. (define funcq-memo (make-hash-table size))
  81. (lambda args
  82. (let* ((key (cons base-func args))
  83. (cached (hashx-ref funcq-hash funcq-assoc funcq-memo key not-found)))
  84. (if (not (eq? cached not-found))
  85. (begin
  86. (funcq-buffer key)
  87. cached)
  88. (let ((val (apply base-func args)))
  89. (funcq-buffer key)
  90. (hashx-set! funcq-hash funcq-assoc funcq-memo key val)
  91. val)))))