What's up with require vs use vs import vs refer?

802 views
Skip to first unread message

j-g-faustus

unread,
May 13, 2010, 2:06:36 PM5/13/10
to Clojure
Hi,

just started looking at Clojure, and it looks promising as a modern-
day Lisp for practical use.

I saw this presentation on Clojure: http://clojure.blip.tv/ and I
wholeheartedly agree with the design principles. Unified access to all
kinds of collections (list, array, struct, hash) is something I sorely
missed in CL back in the day (late 90's), and I like the focus on
practical programming in the modern world (multicore/multithread,
leveraging existing libraries, a stable and mature VM plaform etc.).
Looking forward to getting to know Clojure better.

But I have a question: Why are there *four* ways to do an import, each
with slightly different syntax and semantics?

Re-quoting A. N. Whitehead ("civilizations advance by extending the
number of operations we can perform without thinking") and Occam's
razor ("entities should not be multiplied beyond necessity"), it just
seems strange that after spending tons of effort on unifying
collections the language would start heaping complexity upon the poor
"import".

So my question is: Are all these variants just temporary cruft that
will be collapsed to a uniform way of doing it some time in the
future? Or must we assume that they are here to stay?

Apart from that, what I have seen of the language so far (admittedly
only a couple of days) is impressive. Thanks!

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Brian Hurt

unread,
May 13, 2010, 2:33:53 PM5/13/10
to clo...@googlegroups.com
On Thu, May 13, 2010 at 2:06 PM, j-g-faustus <johannes...@gmail.com> wrote:
Hi,

just started looking at Clojure, and it looks promising as a modern-
day Lisp for practical use.

I saw this presentation on Clojure: http://clojure.blip.tv/ and I
wholeheartedly agree with the design principles. Unified access to all
kinds of collections (list, array, struct, hash) is something I sorely
missed in CL back in the day (late 90's), and I like the focus on
practical programming in the modern world (multicore/multithread,
leveraging existing libraries, a stable and mature VM plaform etc.).
Looking forward to getting to know Clojure better.

But I have a question: Why are there *four* ways to do an import, each
with slightly different syntax and semantics?

:refer shouldn't be used by you at all.

:import brings in java classes

:use brings in the names from another clojure namespace without requiring namespace qualifications

:require brings in the names from another clojure namespace requiring namespace qualifications.

So if ns foo has a var bar, if you do (use 'foo), you can just refer to bar, but if you do (require 'foo), you have to say foo/bar, not just bar.

It is quite common for me to use all three, use, require, and import, in the same namespace declaration, as they do three different things.

If I had to get rid of one, I'd get rid of use.  But it's nice in some circumstances.

Brian

Stuart Halloway

unread,
May 13, 2010, 2:48:51 PM5/13/10
to clo...@googlegroups.com
There needs to be more than one thing, but what we have could
definitely be simpler. Check out these threads and join the discussion:

http://bit.ly/a76XSI (dev list ns overhaul discussion)
http://bit.ly/ajcu74 (dev list "need" proposal)

Stu

j-g-faustus

unread,
May 14, 2010, 12:17:46 PM5/14/10
to Clojure
Thanks for responses and links.

It looks like I can't comment on those threads without signing up as a
Clojure contributor (by postal mail, even) which is a bit more
commitment than I'd like right now, so I'll post my comments here
instead.

I disagree with Stuart Sierra in the "need" proposal that importing
Java classes and Clojure namespaces are "fundamentally different and
should not be conflated".

I just want to say "let me use that code over there", where "over
there" is a namespace. Why should "there" be a fundamentally different
concept for Java than for Clojure, except under the hood? One of the
goals of Clojure is to minimize the Java impedance mismatch, isn't it?

I'll call the import construct XXX to separate the discussion of what
to call it from the syntax and semantics, but it is assumed to be a
single construct that covers all normal use cases.

My proposal would look pretty much the same as the "need" proposal
except for

* Java:
- Treats Java the same as Clojure to the extent possible
- Treats Java static inner classes as a namespace
- Handles Java static methods and fields as Java's "import static"

* Default namespace alias:
- Default to create a namespace alias from the last segment of the
imported namespace.
This idea is lifted from Go, and the rationale is to "make the
right thing easy" - by default it does not clobber the local namespace
and still gives a reasonably short ns alias.

* Keywords:
- No keyword :all, :all is the default behavior
(maybe a keyword :none if there is a usecase for doing an import
without importing anything?)
- Keyword :except renamed to :not (it's shorter) and skipping the
extra array as
argument - :not is presumably used instead symbols/classes, not in
addition to.
So (XXX [clojure.contrib.io :not spit])
instead of
(need [clojure.contrib.io :exclude [spit]])
- New keyword :local to get the behavior of "use" and "import"


Some examples of how it would look:

Import all, default ns alias:

(XXX
clojure.contrib.str-util
java.util
java.awt.Color
com.google.protobuf.Descriptors$FieldDescriptor
)

Use:
(str-util/chop " a ") => clojure.contrib.str-util/chop
(util.ArrayList.) => java.util.ArrayList
Color/green => java.awt.Color/green
;; Static inner class com.google.protobuf.Descriptors
$FieldDescriptor$Type.
;; Unify packages, classes and static inner classes, they are all
namespaces.
;; The Java name is Descriptors$FieldDescriptor$Type.
;; Replace $ with . to get a more uniform ns-like name?
FieldDescriptor.Type/TYPE_BYTES
=> com.google.protobuf.Descriptors$FieldDescriptor$Type/TYPE_BYTES


Import with ns alias:

(XXX
[clojure.contrib.str-util2 :as su]
[java.util :as ju]
[java.awt.Color :as awt-color]
[com.google.protobuf.Descriptors$FieldDescriptor :as fd]
)

Use:
(su/trim " a ")
(ju.ArrayList.)
awt-color/red
(awt-color/decode "#00ffcc")
fd.Type/TYPE_BYTES


Import only some:

(XXX
[clojure.contrib.str-util chop] ;; only chop
[java.util ArrayList Arrays Collections] ;; only ArrayList, Arrays,
Collections
[java.awt.Color :not black blue] ;; all except black and blue
)

Use:
(str-util/chop " a ") = OK
(str-util/chomp "a\n") => Error
(util.ArrayList.) => OK
(util.LinkedList.) => Error
Color/red => OK
Color/black => Error
FieldDescriptor.Type/TYPE_BYTES


Import into current namespace:

(XXX
[clojure.contrib.str-util2 trim :local]
;; same as (use '[clojure.contrib.str-util2 :only (trim)])
[java.util :local]
[java.awt.Color :local]
[com.google.protobuf.Descriptors$FieldDescriptor :local]
)

Use:
(trim " a ")
(ArrayList.)
black
Type/TYPE_BYTES


So what do you think?


On May 13, 8:48 pm, Stuart Halloway <stuart.hallo...@gmail.com> wrote:
> There needs to be more than one thing, but what we have could  
> definitely be simpler. Check out these threads and join the discussion:
>
> http://bit.ly/a76XSI (dev list ns overhaul discussion)
> http://bit.ly/ajcu74  (dev list "need" proposal)
>
> Stu
>

Reply all
Reply to author
Forward
0 new messages