I assume that you are trying to implement a queue . This can be done in several ways, but if you want the insert and delete operation to be performed at a constant time, O (1), you must save the link to the front and back of the queue.
You can save these links in a cons cell or, as in my example, wrapped in closure.
The terminology push and pop commonly used when working with stacks, so I changed them to enqueue and dequeue in the code below.
(define (make-queue)
(let ((front '())
(back '()))
(lambda (msg. obj)
(cond ((eq? msg 'empty?) (null? front))
((eq? msg 'enqueue!)
(if (null? front)
(begin
(set! front obj)
(set! back obj))
(begin
(set-cdr! back obj)
(set! back obj))))
((eq? msg 'dequeue!)
(begin
(let ((val (car front)))
(set! front (cdr front))
val)))
((eq? msg 'queue-> list) front)))))
make-queue returns a procedure that wraps the state of the queue in the front and back variables. This procedure receives different messages that will execute the queue data structure procedures.
This procedure can be used as follows:
> (define q (make-queue))
> (q 'empty?)
#t
> (q 'enqueue! 4)
> (q 'empty?)
#f
> (q 'enqueue! 9)
> (q 'queue-> list)
(4 9)
> (q 'dequeue!)
4
> (q 'queue-> list)
(nine)
This is almost object-oriented programming on a schema! You can think of front and back as private members of the queue class, and messages as methods.
The calling conventions are slightly behind, but it's easy to port the queue to a more convenient API:
(define (enqueue! queue x)
(queue 'enqueue! x))
(define (dequeue! queue)
(queue 'dequeue!))
(define (empty-queue? queue)
(queue 'empty?))
(define (queue-> list queue)
(queue 'queue-> list))
Edit:
As Eli points out, pairs are immutable by default in the PLT scheme, which means there is no set-car! and set-cdr! . For code to work on the PLT Scheme, you must use mutable pairs instead. In the standard circuit (R4RS, R5RS or R6RS), the code should work without changes.