Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rename using (ns (:require :refer))

My understanding is that it is recommended now to use require :refer instead of use in the ns macro. For example, do:

(ns example.core 
  (:require [clj-json.core :refer [parse-string]]))

instead of

(ns example.core 
  (:use [clj-json.core :only [parse-string]]))

What is the recommended way to deal with :rename which use supports? Specifically, let's say I want to require clojure.data.zip and rename the ancestors and descendants functions which conflict with clojure.core.

In other words I'd like to know the require equivalent for

(:use 
  [clojure.data.zip :rename {ancestors xml-ancestors, 
                             descendants xml-descendants})
like image 832
apolenur Avatar asked Jan 30 '13 18:01

apolenur


3 Answers

(ns foo
  (:require [clojure.data.zip :refer [ancestors descendants] :rename {ancestors xml-ancestors descendants xml-descendants}]))
like image 108
user1338062 Avatar answered Nov 05 '22 05:11

user1338062


You :require in one step, and then :refer with :rename in the next.

(ns foo
  (:require clojure.data.zip)
  (:refer [clojure.data.zip :rename {ancestors xml-ancestors,
                                     descendants xml-descendants})

:use has always been a shorthand for :require+:refer, and now the :refer option to :require is a shorthand for the simplest kind of refer.

like image 25
amalloy Avatar answered Nov 05 '22 06:11

amalloy


Disclaimer: I do not know the "recommended" way to do this. I only know how I would do it. My solution may not be idiomatic Clojure, and I would be surprised if nobody came along with a better answer.


Here's what I would do: :require the package and alias it using :as:

(ns some.big.name.space
  (:require [clojure.data.zip  :as  cdz])
  ... some more imports, maybe ...)

Then the symbols can be accessed using the specified prefix, and don't conflict with any symbols in my some.big.name.space namespace:

(def some-list [cdz/ancestors cdz/descendants ancestors descendants])

If the alias is short, it hardly bothers me to type it, and I feel that my code is clearer -- the cdz/ is a nice visual cue that the symbol is an import.

I know that this doesn't really answer your exact question -- how to use :rename with :require -- but I feel that it's worth mentioning because it avoids polluting my namespaces and I don't have to mess with Clojure's symbol resolution mechanisms.

like image 29
Matt Fenwick Avatar answered Nov 05 '22 05:11

Matt Fenwick