Head And Tail

November 13, 2015

We read the file by line, writing the first line when we see it, then saving each line as we read the next until reaching the end of the file, when we write the saved line:

(define (head&tail file-name)
  (with-input-from-file file-name
    (lambda ()
      (let ((prev (read-line)))
        (display prev) (newline)
        (let loop ((line (read-line)) (prev prev))
          (if (eof-object? line)
              (begin (display prev) (newline))
              (loop (read-line) line)))))))

And here’s a sample run:

> (head&tail "gettysburg")
Four score and seven years ago,
shall not perish from the earth.

We used read-line from the Standard Prelude. You can run the program at http://ideone.com/qlfpFR, where the program has been modified to read standard input.

Pages: 1 2

11 Responses to “Head And Tail”

  1. FA said

    Scala with iterator

      def headAndTail(in: String) = {
        val lines = Source.fromFile(in).getLines()
        while (lines.hasNext) {
          val last = lines.next
          if (!lines.hasNext) println(last)
  2. Francesco said


    (\x -> [head x, last x]) . lines <$> readFile "file.txt"
  3. klettier said

    FSharp :

    let writeLastAndFirstLines = fun x -> File.ReadAllLines(x) >> fun x -> (Array.head x, Array.last x) >> fun x -> printfn "%s\n%s" (fst x) (snd x)
    "test.txt" |> writeLastAndFirstLines
  4. wert310 said


    headTail filename = (liftM lines $ readFile filename) >>=
                        mapM_ putStrLn . (zipWith ($) [head,last]) . repeat
  5. John Cowan said

    head -1 $1; tail -1 $1

  6. Jussi Piitulainen said

    I memory-mapped the file as a byte array. I wanted to learn about that.

    A source says it is guaranteed that an ASCII byte cannot occur in the middle of a UTF-8 character; other assumptions about what line-end characters occur where in the file remain because I couldn’t be bothered.

    # tiedoston ht.jl ensimmäinen rivi
    """Displays the first and last line of the named file, assuming way
       too much about the byte-level contents of the files."""
    function peek(name)
        s = Mmap.mmap(name, Array{UInt8,1}, filesize(name))
        print("head: ", utf8(s[1:findfirst(s, 0x0a)]))
        print("tail: ", utf8(s[findprev(s, 0x0a, end - 1) + 1:end]))
    # tiedoston ht.jl viimeinen rivi

    Testing with the source code file itself:

    $ julia ht.jl ht.jl
    head: # tiedoston ht.jl ensimmäinen rivi
    tail: # tiedoston ht.jl viimeinen rivi
  7. Sia said

    // C#:
    string[] lines = File.ReadAllLines(@”file.txt”);
    if (lines.Length != 0)
    MessageBox.Show(lines[0] + “\n” + lines[lines.Length – 1]);

  8. matthew said

    Here’s a C++ solution that just uses some basic Unix system functions – sbrk and brk for memory allocation, read and write for I/0. Probably should check return codes & allow for partial writes. Could be more intelligent about copying data from the input buffer too.

    #include <unistd.h>
    #include <fcntl.h>
    static const size_t BSIZE = 256;
    int main(int argc, char *argv[]) {
      int fd = (argc == 1) ? 0 : open(argv[1], O_RDONLY);
      char *buff = (char*)sbrk(2*BSIZE); // Allocate
      char *start = buff + BSIZE, *end = start + BSIZE;
      char *p = start;
      bool first = true;
      while (true) {
        ssize_t n = read(fd,buff,BSIZE);
        if (n <= 0) break;
        for (ssize_t i = 0; i < n; i++) {
          if (p > start && *(p-1) == '\n') {
            if (first) write(1,start,p-start);
            first = false;
            p = start;
          if (p == end) brk(end += BSIZE); // Extend
          *p++ = buff[i];
  9. ;; A Simple Clisp solution

    (defun head-tail(name)
    (let (last)
    (with-open-file (file name)
    (print (read-line file))
    (loop for x = (read-line file nil) while x do
    (setf last x))
    (print last))))

  10. fisherro said

    Using the Reverse_file_buf from my solution to the 17 November 2015 exercise…

    It’s pretty fast even on large files (despite the inefficiencies of Reverse_file_buf) because it jumps straight to the end to find the last line.

    #include <algorithm>
    #include <cctype>
    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    #include "Reverse_file_buf.hpp"
    //Ignores lines with only whitespace or control characters.
    //Not Unicode friendly.
    std::string find_first_line(std::istream& in)
        std::string line;
        while (std::getline(in, line)) {
            if (std::any_of(line.begin(), line.end(), ::isgraph)) {
                return line;
        return "";
    int main(int argc, char** argv)
        std::vector<std::string> args(argv + 1, argv + argc);
        if (args.empty()) args.push_back("praxis.cpp");
        for (auto arg: args) {
            std::ifstream forwards(arg);
            std::cout << find_first_line(forwards) << '\n';
            Reverse_file_buf rfb(arg);
            std::istream backwards(&rfb);
            auto line = find_first_line(backwards);
            std::reverse(line.begin(), line.end());
            std::cout << line << '\n';
  11. r. clayton said

    Some Racket Scheme solutions .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: