git @ Cat's Eye Technologies The-Dossier / master article / Information-Hiding-in-Scheme / information-hiding.scm
master

Tree @master (Download .tar.gz)

information-hiding.scm @masterraw · history · blame

;
; information-hiding.scm
; A simple technique to accomplish information hiding in R5RS Scheme.
;
; SPDX-FileCopyrightText: In 2023, Chris Pressey, the original author of this work, placed it into the public domain.
; SPDX-License-Identifier: Unlicense
; For more information, please refer to <https://unlicense.org/>
;

(define stack-module (lambda ()
  (let* ((secret-token (list 1))
         (seal         (lambda (data)
                         (lambda (token)
                           (if (eq? token secret-token)
                             data
                             'an-error-occurred))))
         (open         (lambda (opaque-object)
                         (opaque-object secret-token)))

         (new-stack    (lambda ()
                         (seal '())))
         (is-empty?    (lambda (stack)
                         (equal? (open stack) '())))
         (push         (lambda (stack item)
                         (let* ((data      (open stack))
                                (new-data  (cons item data))
                                (new-stack (seal new-data)))
                           new-stack)))
         (top          (lambda (stack)
                         (car (open stack))))
         (popped       (lambda (stack)
                         (let* ((data      (open stack))
                                (new-data  (cdr data))
                                (new-stack (seal new-data)))
                           new-stack))))
    (list new-stack is-empty? push top popped))))

(define skm       (stack-module))
(define new-stack (car skm))
(define is-empty? (cadr skm))
(define push      (caddr skm))
(define top       (cadddr skm))
(define popped    (car (cddddr skm)))

;
; A transcript of some sample usage that shows that it implements a stack:
;
; #;1> (define s (new-stack))
; #;2> (define t (push s 4))
; #;3> (define u (push t 5))
; #;4> (top u)
; 5
; #;5> (top (popped u))
; 4
; #;6> (is-empty? s)
; #t
; #;7> (is-empty? (popped t))
; #t
; #;8> (popped s)
;
; Error: (cdr) bad argument type: ()
;

;
; And a transcript that shows that it hides the representation:
;
; #;8> s
; #<procedure (? token)>
; #;9> t
; #<procedure (? token)>
; #;10> top
; #<procedure (top stack)>
; #;11> (s 1)
; an-error-occurred
; #;12> (s (list 1))
; an-error-occurred
; #;13> (is-empty? (list 1))
;
; Error: call of non-procedure: (1)
;