In this post on the PLT discussion list I sleepily wondered how to do something to all elements of a list but the last.
The reasons I asked is because I had used ‘do’ loops in lieu of something better, and from what I can gather, you basically never write ‘do’ loops in Scheme (maybe once every 30 years you do use ‘do’).
I hastily posted a solution using the ‘match’ library as I had just read the documentation while cutting over from ‘mzlib/match’ to ‘match’. Both Robby and Ethan replied with much, much faster solutions. Have a look:
#lang scheme (require (prefix-in srfi/1: srfi/1)) ; Grant's (define (foo1 args fun last-fun) (match args [(list arg args ..1) (fun arg) (foo1 args fun last-fun)] [(list arg) (last-fun arg)])) (provide/contract [foo2 (-> (cons/c any/c (listof any/c)) (-> any/c any) (-> any/c void?) void?)]) ; Robby's (define (foo2 args fun last-fun) (let loop ([fst (car args)] [rst (cdr args)]) (cond [(empty? rst) (last-fun fst)] [else (fun fst) (loop (car rst) (cdr rst))]))) (define data (srfi/1:make-list 10000 "hi")) ; Ethan's (define (foo3 lst fun funl) (begin (for-each fun (srfi/1:drop-right lst 1)) (funl (srfi/1:take-right lst 1)))) (time (foo1 data (λ (x) (void)) (λ (x) (void)))) (time (foo2 data (λ (x) (void)) (λ (x) (void)))) (time (foo3 data (λ (x) (void)) (λ (x) (void)))) > cpu time: 2593 real time: 2625 gc time: 718 > cpu time: 0 real time: 0 gc time: 0 > cpu time: 0 real time: 0 gc time: 0
In the end, I only needed this functionality in two places, and I probably would not have required it if I had designed things better in the first place.