I recently learned (thanks to technomancy) that, at the REPL ---
This fails:
user=> (:require [clojure.set :as set]) java.lang.ClassNotFoundException: clojure.set (NO_SOURCE_FILE:24)
Whereas this succeeds :
user=> (require '[clojure.set :as cs]) nil
at loading the clojure.set class.
Context: The former line was copied from a namespaced source file.
My primary question is : What is the change we have made, by swapping the : and ' characters, which now allows for success of the latter command ?
My 2nd question is , in general - what are the guidelines for doing things at the REPL --- as compared with doing things in normal clojure source files ? Assume here that we can load our repl from the root of a LEININGEN project, so at least the jars will be available on disk in the dependencies sub directory.
I'll go from high-level down to your particular problem:
REPLs, or Read-Eval-Print Loops are the core of how LISPs are designed:
So when you enter text into a REPL, it goes through each of these steps to process your input and return the output to your terminal.
First some, clojure reader forms. This will be extremely brief, I encourage you to read or watch (part 1, part 2) about it.
A symbol in clojure is form that can represent a particular value (like a variable). Symbols themselves can be pass around as data. They are similar to pointers in c, just without the memory management stuff.
A symbol with a colon in front of it is a keyword. Keywords are like symbols with the exception that a keyword's value are always themselves - similar to strings or numbers. They're identical to Ruby's symbols (which are also prefixed with colons).
A quote in front of a form tells the evaluator to leave the data structure as-is:
user=> (list 1 2) (1 2) user=> '(1 2) (1 2) user=> (= (list 1 2) '(1 2)) true
Although quoting can apply to more than just lists, it's primarily used for lists because clojure's evaluator will normally execute lists as a function-like invocation. Using the '
is shorthand to the quote macro:
user=> (quote (1 2)) ; same as '(1 2) (1 2)
Quoting basically specifies data structure to return and not actual code to execute. So you can quote symbols which refers to the symbol.
user=> 'foo ; not defined earlier foo
And quoting is recursive. So all the data inside are quoted too:
user=> '(foo bar) (foo bar)
To get the behavior of (foo bar)
without quoting, you can eval it:
user=> (eval '(foo bar)) ; Remember, foo and bar weren't defined yet. CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:1) user=> (def foo identity) #'user/foo user=> (def bar 1) #'user/bar user=> (eval '(foo bar)) 1
There's a lot more to quoting, but that's out of this scope.
As for require statements, I'm assuming you found the former in the form of:
(ns my.namespace (:require [clojure.set :as set]))
ns
is a macro that will transform the :require expression into the latter form you described:
(require '[clojure.set :as set])
Along with some namespacing work. The basics are described when asking for the docs of ns in the REPL.
user=> (doc ns) ------------------------- clojure.core/ns ([name docstring? attr-map? references*]) Macro Sets *ns* to the namespace named by name (unevaluated), creating it if needed. references can be zero or more of: (:refer-clojure ...) (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class) with the syntax of refer-clojure/require/use/import/load/gen-class respectively, except the arguments are unevaluated and need not be quoted. (:gen-class ...), when supplied, defaults to :name corresponding to the ns name, :main true, :impl-ns same as ns, and :init-impl-ns true. All options of gen-class are supported. The :gen-class directive is ignored when not compiling. If :gen-class is not supplied, when compiled only an nsname__init.class will be generated. If :refer-clojure is not used, a default (refer 'clojure) is used. Use of ns is preferred to individual calls to in-ns/require/use/import:
In general, don't use ns
in the REPL, and just use the require
and use
functions. But in files, use the ns
macro to do those stuff.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With