Search code examples
clojure

Issue with dependencies & function being recognized in the repl


I am having a similar issue to this person: Problems while creating a deps.edn file

However, I'm on MacOS and trying to follow the book and use deps.edn instead of leiningen, so I wasn't able to solve my issue from reading the answers in that post.

I'm using my terminal window and just text files, or Emacs.

Within the terminal, I created a folder called tennisProject. Then I created 2 files, deps.edn and tennisProject.clj inside that folder. Then I put the csv file of tennis data in that folder.

Then I go back to the terminal and restart it. I make tennisProject the current directory. I type in "clj" to start a repl. Then I do (in-ns 'packt-clj.tennisProject) to get into the right namespace. Then, I type (first-match "match_scores_1991-2016_unindexed_csv.csv"), and I get an error:

Syntax error compiling at (REPL:1:1). Unable to resolve symbol: first-match in this context

The contents are as follows (I copied and pasted from the book).

deps.edn:

{:deps
 {org.clojure/data.csv {:mvn/version "1.0.0"}
  semantic-csv/semantic-csv {:mvn/version "0.2.1-alpha1"}}}

tennisProject.clj:

(ns packt-clj.tennisProject
  (:require
   [clojure.data.csv :as csv]
   [clojure.java.io :as io]
   [semantic-csv.core :as sc]))


(defn first-match [csv]
  (with-open [r (io/reader csv)]
    (->> (csv/read-csv r)
         sc/mappify
     first)))

I have a few things different than the book: I changed the name from tennis to tennisProject because I kept making new folders after getting errors. I also changed the data.csv version from "0.1.4" to "1.0.0" because that's what was in the answer I linked, but that didn't resolve my issue. Then I also have semantic-csv/semantic-csv but in the book it's just semantic-csv. I changed that because the repl advised me to make the change.

If I just require the dependencies one by one in the repl, and define the function in the repl, everything works fine, but I really want to understand how all these files work together and I appreciate your help!


Solution

  • By default, the Clojure CLI / deps.edn assumes your source code is going to be in a tree under a folder called src.

    The namespace in a Clojure file must "match" its filepath relative to src so for packt-clj.tennisProject, the file should be src/packt_clj/tennisProject.clj -- note the - in a namespace corresponds to an _ in the filepath.

    If you reorganize your project like that, and restart your REPL, you should be able to require your code and work with it.

    As a stylistic note, we don't use camelCase much in Clojure: it would be more idiomatic to have tennis-project as the namespace (which means tennis_project.clj as the filename).

    (edited to add this example session)

    (! 556)-> pwd
    /Users/sean/clojure/tennisProject
    (! 557)-> ls
    deps.edn    example.csv src
    (! 558)-> tree
    .
    |____deps.edn
    |____example.csv
    |____src
    | |____packt_clj
    | | |____tennisProject.clj
    (! 559)-> clj
    Clojure 1.10.3
    user=> (require 'packt-clj.tennisProject)
    nil
    user=> (in-ns 'packt-clj.tennisProject)
    #object[clojure.lang.Namespace 0x128c502c "packt-clj.tennisProject"]
    packt-clj.tennisProject=> (first-match "example.csv")
    {:some "42", :headers "A value", :in "1", :this "2", :file "3.333"}
    packt-clj.tennisProject=> ^D
    (! 560)-> cat src/packt_clj/tennisProject.clj 
    (ns packt-clj.tennisProject
      (:require
       [clojure.data.csv :as csv]
       [clojure.java.io :as io]
       [semantic-csv.core :as sc]))
    
    
    (defn first-match [csv]
      (with-open [r (io/reader csv)]
        (->> (csv/read-csv r)
             sc/mappify
         first)))
    (! 561)-> cat example.csv 
    some,headers,in,this,file
    42,"A value",1,2,3.333