views:

428

answers:

2

I have a program that draws shapes on an image. I have a separate namespace for each shape, and they are in separate files.


com/name/box.clj --> has com.name.box namespace.
com/name/triangle.clj --> has com.name.triangle namespace.

They all share a common function called generate that draws them on screen, so if I use use, function names clash.

For now, I load them with load-file. Is there a better way of doing this? Looking through the Clojure API, it seems there are multiple ways of including files. Which one is a better option for a project with lots of files?

+7  A: 

I too started by using load-file. According to the Clojure documentation on libs,

Clojure defines conventions for naming and structuring libs:
    * A lib name is a symbol that will typically contain two or more parts separated by periods.
    * A lib's container is a Java resource whose classpath-relative path is derived from the lib name:
        o The path is a string
        o Periods in the lib name are replaced by slashes in the path
        o Hyphens in the lib name are replaced by underscores in the path
        o The path ends with ".clj"
    * A lib begins with an "ns" form that
        o creates the Clojure namespace that shares its name, and
        o declares its dependencies on Java classes, Clojure's core facilities, and/or other libs

The Clojure documentation further provides the following example namespace declaration (which I'm sure you already know, but I'm providing it here for completeness):

(ns com.my-company.clojure.examples.my-utils
  (:import java.util.Date)
  (:use [clojure.contrib.def :only (defvar-)])
  (:require [clojure.contrib.shell-out :as shell]))

So, my answer would be to use libs for your project -- it'll help simplify all of those folders. To "include" a lib, you'll use require, like this:

(require 'clojure.contrib.def 'clojure.contrib.except 'clojure.contrib.sql)
(require '(clojure.contrib def except sql))

As long as the documentation is correct and your project is classpath-relative, everything should happily load. Hope that answers your question. :D

Zachary Murray
+4  A: 

Along with using namespace libs as already has been suggested perhaps your common 'generate' function is a candidate for a multimethod? http://clojure.org/multimethods

This would help avoid the function name clash and add a common abstraction to your 'shapes', I guess it depends on whether an appropriate dispatch function can be found.

James Sofra