Sunday, February 8, 2015

Towards a better dir function in Clojure. (pt. 1)

Coming from Python, for the most part, I felt right at home in the Clojure REPL. However, one of my trustiest old tricks in the Python interpreter didn't work nearly as well in Clojure.

I'm referring, of course, to the "what the hell was that called again?" fixer: dir.

In Python, dir will get you the fns/classes in a namespace, but the first major obstacle in clojure is the lack of support for namespace aliases.

Let's fix that, shall we?

Looking at the source for the dir macro, we find:

user> (source dir)
(defmacro dir
  "Prints a sorted directory of public vars in a namespace"
  [nsname]
  `(doseq [v# (dir-fn '~nsname)]
     (println v#)))

Ok, this is really no more than a bit of sugar, to save us having to quote the namespace and to print the vars on their own line.  We'll have to dig deeper for some meat.

user> (source dir-fn)
(defn dir-fn
  "Returns a sorted seq of symbols naming public vars in
  a namespace"
  [ns]
  (sort (map first (ns-publics (the-ns ns)))))

One thing I really love about Lisps: many times when I look under the hood, I'm expecting a monstrous Rube Goldberg machine, but what I find is some beautifully simple thing, that will still be pretty much the same thing in 50 years.  (Go back and read some of the early algorithmic lisp code, it comes very easy.)

The first part of dir that bugs me is you must specify the full namespace, even if you've aliased it to something much simpler.

(ns yournamespace
  (:require [clojure.string as str]
            [clojure.repl :refer :all]))

(dir str)
=> Exception No namespace: str found  clojure.core/the-ns (core.clj:3830)

user> (dir clojure.string)
blank?
capitalize
escape
...

You can get aliases via ns-aliases, so...

(defn alias-dir-fn [nsname]
  (-> (ns-aliases *ns*)
      (get nsname) ; look up the alias or nil trying
      (or nsname)
      dir-fn))

(defmacro alias-dir
  "Prints a sorted directory of public vars in a namespace or an alias
  namespace."
  [nsname]
  `(doseq [v# (alias-dir-fn '~nsname)]
     (println v#)))

Now we can...

user> (alias-dir str)
blank?
capitalize
escape
...

But I'm not done with dir yet.  Stay tuned for part 2.

Edit: I've filed a ticket for this functionality to be added to Clojure

2 comments:

Anonymous said...

Upgrade your collection of legendary legendary beings by collecting chests and tokens. Mike Dixon, PhD, professor of psychology on the University of 우리카지노 Waterloo, research the relationship between slot gamers and machines. In one of Dixon's research, gamers have been noticed experiencing heightened arousal from the sensory stimulus coming from the machines.

j367ritfxs said...

If you suppose you can to|you probably can} win with only one extra card dealt, you might double your bet for the same or a lesser worth and obtain one additional card only. • If the participant and the player-dealer’s palms complete twenty-one or much less and are the identical complete, the palms push and no motion is taken on the wager. The vendor then goes around the 메리트카지노 desk to ask every participant whether they want to stick to the 2 cards they've or be dealt an extra card to get closer to 21. If a participant betting a flat $5 a hand wins six palms in a row, winnings complete $30. The development bettor has won two palms at $5, two at $10, and two at $15 for $60. Nothing you can draw might harm a delicate 16, or a delicate 15, or many different delicate totals.