## [Racket] SplitBy function I always wanted + fortune program in ~5 SLOC

A function in Wolfram Mathematica:

```SplitBy[list,f]
splits list into sublists consisting of runs of successive elements that give the same value when f is applied.
```

( src )

The function is incredibly useful when parsing, for example, a fortune file, which is present in any *NIX system, like:
```the more general problem may be easier to solve
-- G.Polya
%
The world doesn't live off jam and fancy perfumes - it lives off bread and meat and potatoes. Nothing changes. All the big fancy stuff is sloppy stuff that crashes. I don't need dancing baloney - I need stuff that works. That's not as pretty, and just as hard.
%
As a friend of mine, the computer scientist Guy Steele, once put it, “LISP is a high-level language, but you can still feel the bits sliding between your toes.”
-- Daniel Hillis -- The Pattern On The Stone: The Simple Ideas That Make Computers Work
%
```

How do you pick a random element if it may consist of several lines? Here I split the fortune file using my own reimplementation of this function in Racket:

```#lang racket

; another function I didn't find:
(provide pick-random)
(define (pick-random lst)
(list-ref lst (random (length lst))))

; works almost like http://reference.wolfram.com/language/ref/SplitBy.html in Mathematica:
(define (drop-first-elem-if l pred)
(if (pred (first l))
(drop l 1)
l))

(define (drop-empty-lists l)
(filter (λ (x) (not (null? x))) l))

(provide split-list-into-sublists)
(define (split-list-into-sublists xs pred)
(if (null? xs)
'()
(let* ((new-list (drop-first-elem-if xs pred))
(first-chunk (takef new-list (negate pred)))
(rest-of-list (dropf new-list (negate pred))))
(cons first-chunk (drop-empty-lists (split-list-into-sublists rest-of-list pred))))))

; main program

(define (pick-random-fortune-from filename)
(define sliced
(split-list-into-sublists
(file->lines filename)
(λ (n) (equal? "%" n))))
(map (λ (s) (displayln s)) (pick-random sliced))) ; print each line

(void (pick-random-fortune-from "/home/i/tmp/fortunes.txt")) ; "void" to suppress printing "void"
```

Isn't it nice? Of course, my implementation is crude and slow. If you can suggest better or more efficient, please drop me email.

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.