0

I've started working on a chess game in Clojure, but am having trouble with my namespace. At the top of my file, I have

(ns chess.core
    (:require clojure.contrib.str-utils2))

and also define several functions, including to-string, which turns the symbol for a game piece into a string. However, when I compile:

core.clj:21:8:
  error: java.lang.Exception: Unable to resolve symbol: to-string in this context (core.clj:21)

I've done some experimenting, and discovered that I get an error the first time I call a function that I defined myself. I've also discovered that I usually don't get an error if I comment out the ns call. Sometimes it can be fixed by restarting the Swank server (and sometimes it can't). For a while I just had (ns chess.core), which threw the same error, so I commented it out and continued hacking. But now I need to upper-case something, so I need str-utils.

Speaking about str-utils, I use Leiningen, and have the following in project.clj under :dependencies:

                 [org.clojars.jhowarth/clojure-contrib "1.2.0-RC3"]]
;                [clojure.contrib.str-utils2 "1.2.1"]]

The top one works, the bottom one doesn't.

So I feel like I'm just ignorant about how Clojure namespacing and libraries work, but at the same time everyone else seems to be using (ns foo.bar) successfully.

tsm
  • 3,598
  • 2
  • 21
  • 35

2 Answers2

0

When compiling, the definitions are evaluated from top to bottom. If you refer to a function that is defined later in the file, you'll get that error. I'm thinking that by removing the ns at the top, you're actually referring to a function with the same name in another namespace (probably the default user ns).

If you can't move the function to above its first use, you can do a (declare to-string) at the top and define it later.

As for the str-utils2 package, it should already be in clojure-contrib 1.2X. Starting from 1.3 (which isn't finished), contrib will be split up. See http://groups.google.com/group/clojure/msg/c5cdfec990efb6f4

Joost Diepenmaat
  • 17,633
  • 3
  • 44
  • 53
  • Thanks! Now I know that Clojure has a one-pass compiler. I'm kind of surprised that doesn't appear more prominently on the website...like [here](http://clojure.org/lisps). And that's good to know about `(declare)`, but I'm guessing I should put a little more thought into how I split my project into several files. – tsm Apr 22 '11 at 15:09
  • Most lisps only do a single pass compilation, since it's very common to (re)compile and load single statements while developing instead of whole files. Clojure also expects all free variables to be defined when compiling, which is where the error is coming from, but I suspect that's mostly for performance/interop reasons, since Common Lisp for example doesn't enforce that. – Joost Diepenmaat Apr 22 '11 at 15:29
  • [Here](http://news.ycombinator.org/item?id=2467809)'s what Rich Hickey has to say about it. It's a deliberate design decision. – tsm Apr 22 '11 at 23:32
0

It's hard to say without seeing your use of the to-string function, but you might check out this explanation of how require, ns, and use work: http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns. It captures the things I personally found confusing about libs and namespaces.

trptcolin
  • 2,320
  • 13
  • 16