HiveBrain v1.2.0
Get Started
← Back to all entries
snippetMinor

Unix sort in Clojure

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
sortunixclojure

Problem

I am implementing Unix sort in Clojure. This is my first program, and I would like some feedback regarding any non-idiomatic, harmful code and any other best practices I can include in future versions. I tried my best to follow the coding standards, but went with camelCase instead of hyphen-case for variable and function names.

Main class: sort.core

(ns sort.core
  (:gen-class)
  (:use clojure.contrib.core)
  (:use clojure.tools.cli)
  (:require [sort.lib :as lib]))

(defn -main [& args]
  (let [[options args banner] (cli args    
                                   ["-h" "--help" "Show help" :default false :flag true]
                                   ["-i" "--input" "The input file" :default nil]
                                   ["-d" "--delim"  "The delimitter" :default ","]
                                   ["-f" "--field" "The column to parse(1 indexed)" :parse-fn #(Integer. %)])
        {:keys [delim field input]} options]

    (lib/help options args banner)

    (when (= (lib/fileKind input) "file")
        (lib/printOutVector delim
                            (lib/sortVector field
                                            (lib/splitFile input delim ))))

    (System/exit 0)))


Library: sort.lib

```
(ns sort.lib
(:require [clojure.string :as str])
(:import java.io.File))

(defn splitFile
"splits a file into a 2d array"
[s delim]
(pmap #(str/split % (re-pattern delim))
(str/split(slurp s) #"\n")))

(defn printOutVector
"prints out the 2dVector formatted by the delim arg"
[delim coll]
(println
(apply str
(interpose "\n" (map #(apply str (interpose delim %)) coll)))))

(defn sortVector
"sorts a 2d vector by the given index"
[index coll]
(sort-by #(nth % index) coll))

(defn help
"custom help message for sort.core"
[opts args banner]
(when (:help opts)
(println (str "input: " (:input opts)))
(println (str "field: " (:field opts)))
(println (str "delim: " (:delim opts)

Solution

You should use namespace-qualified keywords instead of strings in the fileKind function:

(defn fileKind [filename]
  (let [f (File. filename)]
    (cond
      (.isFile f)      ::file
      (.isDirectory f) ::directory
      (.exists f)      ::other 
      :else            ::non-existent)))


... which would require the following change in the -main function:

(= (lib/fileKind input) :lib/file)

Code Snippets

(defn fileKind [filename]
  (let [f (File. filename)]
    (cond
      (.isFile f)      ::file
      (.isDirectory f) ::directory
      (.exists f)      ::other 
      :else            ::non-existent)))
(= (lib/fileKind input) :lib/file)

Context

StackExchange Code Review Q#8000, answer score: 4

Revisions (0)

No revisions yet.