fapply.csv <-
    function(fname, FUN, ..., nrows=200L, header=TRUE,
             colClasses=NA, col.names, .reduce)
{
    conn <- file(fname, open="r")
    ## first chunk; special: remember header info
    chunk <- read.csv(conn, header=header, ..., nrows=nrows,
                      colClasses=colClasses)
    colClasses <- sapply(chunk, class)
    colNames <- c("", names(chunk))
    result <- list(); it <- 1
    repeat {
        result[[it]] <- FUN(chunk, ...)
        if (nrow(chunk) != nrows) break
        chunk <- read.csv(conn, header=FALSE, ...,
                          nrows=nrows, colClasses=colClasses,
                          col.names=colNames)
        if (nrow(chunk) == 0L) break
        it <- it + 1
    }
    close(conn)
    if (missing(.reduce)) result
    else .reduce(result)
}
