Configure symbol quote expansion in clojure zprint - clojure

Is there a way to avoid having zprint write 'my-symbol as (quote my-symbol)? I am aware it is the reader that converts it to that form.
However I would expect zprint to be configurable to produce the more idiomatic format which is the default for clojure.pprint.
(require '[zprint.core :as zp])
(zp/zprint '(def foo 'my-symbol))
;; (def foo (quote my-symbol))
(require '[clojure.pprint :as pp])
(pp/pprint '(def foo 'my-symbol))
;; (def foo 'my-symbol)

See related issue:
https://github.com/kkinnear/zprint/issues/121
Following bfabry's comment, as a workaround, we can use pprint to create the nicely quoted string, and then pass it through zprint for formatting:
(require '[zprint.core :as zp])
(require '[clojure.pprint :as pp])
(-> '(def foo 'my-symbol)
pp/pprint
with-out-str
(zp/zprint 40 {:parse-string? true}))
(def foo 'my-symbol)
nil

Related

clojure.java.io ClassNotFoundException

I am trying to run the following program on my Mac:
(ns clojure.examples.hello
(:gen-class))
(require ‘clojure.java.io’)
(defn Example []
(.exists (file "Example.txt")))
(Example)
I do this wih the following command:
clojure Exists.clj
But this gives me the following error:
Syntax error (ClassNotFoundException) compiling at (Exists.clj:5:1).
‘clojure.java.io’
How can I go about including the clojure.java.io class?
Here is how you would normally write this in a source code file:
(ns tst.demo.core
(:require [clojure.java.io :as io]) ; proper form, but not used anywhere
(:import [java.io File]))
(println (spit "demo.txt" "stuff happens"))
(println (slurp "demo.txt"))
(println (.exists (java.io.File. "./demo.txt"))) ; will work w/o `:import` above
(println (.exists (File. "./demo.txt"))) ; requires `:import` declaration above
with results:
(spit "demo.txt" "stuff happens") => nil
(slurp "demo.txt") => "stuff happens"
(.exists (java.io.File. "./demo.txt")) => true
(.exists (File. "./demo.txt")) => true
Note that using the :require keyword in a ns form requires different syntax and quoting than using the (require ...) function call.
If you are typing these lines into a REPL, you may do something like:
demo.core=> (ns demo.core)
nil
demo.core=> (require '[clojure.java.io :as io]) ; function-call version
nil
demo.core=> (spit "demo.txt" "stuff happens")
nil
demo.core=> (println (slurp "demo.txt"))
stuff happens
nil
You may find this template project helpful in getting started. Also be sure to check out the list of documentation sources, esp. the Clojure CheatSheet!

clojure - conj doesn't seem to add value to vector

I have written a function which takes a directory as input and returns a list of files.
(ns musicdb.filesystem)
(import '(java.io.File) '(java.net.url) '(java.io))
(use 'clojure.java.browse)
(require '[clojure.string :as str])
(defn getFiles
"get a list of all files"
[searchPath]
(def directory (clojure.java.io/file searchPath))
(def files (file-seq directory))
(def fonly (filter (fn [x]
(. x isFile)) files))
(def names [])
(doseq [x fonly]
(conj names (. x toString)) ;doesn't seem to work
(println (. x toString))) ;but this DOES print the file path
names)
The only thing that doesn't work here, is the conj call.
Here is my test
(ns musicdb.core-test
(:require [clojure.test :refer :all]
[musicdb.core :refer :all]
[musicdb.filesystem :refer :all]))
(deftest test_0
(testing "getFiles returns valid result"
(is (> (count (getFiles "/home/ls/books/books")) 1))
(doseq [i (take 5 (getFiles "/home/ls/books/books"))] (searchBook i))))
This test fails and shows that the return value of getFiles is empty.
names is an immutable vector. (conj names (. x toString)) creates a new vector but doesn't do anything with it. There are other problems with your code:
you don't want to use doseq. It's for side effects, such as printing things out. If you're creating a collection you usually don't need to iterate in clojure, or if you do you can use an immutable accumulator, loop and recur.
You don't want to use nested defs. You're defining globals, and what you want are function locals. Use let instead.
The clojure naming style is to use dashes instead of camel case (minor, just a convention).
You don't seem to be using your java.io importa in this code.
use in general is not a good idea, unless you restrict it to a few explicitly named functions with :only. This is to avoid confusion when looking at an unqualified name in your code, because you wouldn't know where it came from.
You want something like this:
(defn get-files [search-path]
(let [directory (clojure.java.io/file search-path)
files (file-seq directory)
fonly (filter #(.isFile %) files)]
(map #(.toString %) fonly)))

Can't require goog.fx.Dragger in ClojureScript

I'm trying to build a small om-component that uses goog.fx.Dragger to make a target draggable. I require goog.fx.Dragger :as dragger and like so:
(ns om-draggable-me.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[goog.fx.Dragger :as dragger]))
When i use it like:
(defn draggable [app owner]
(reify
om/IDidMount
(did-mount [_]
(let [target (om/get-node owner)]
(dragger. target)))
om/IRender
(render [_]
(dom/div #js {:id "drag-box" :className "drag-box"}))))
I get the compiler warning:
WARNING: Use of undeclared Var om-draggable-me.core/dragger at line 22 src/cljs/om_draggable_me/core.cljs
Seen other examples of the use of goog.fx.DragDrop so why does not this work?
In your require form, dragger is a namespace alias
[goog.fx.Dragger :as dragger]
which is intended to be used like this:
dragger/your-var
;; the same as goog.fx.Dragger/your-var
while in your script, it was used as if it's a var:
(dragger. target)
and, as the compiler complained, such var hasn't been defined.
You can see people refer to clojure.string like this:
(require '[clojure.string :as str])
without worrying about conflicting with clojure.core/str function:
(str/join ", " [1 2 3])
(str "hello" "world")
For some reason the alias did not work, it works with fully qualified name:
(did-mount [_]
(let [target (om/get-node owner)]
(goog.fx.Dragger. target)))

Determine namespace of a function's caller

I'm trying to accurately determine the namespace of a function's caller. Looks like *ns* is determined by the namespace at top of the call stack.
user=> (ns util)
nil
util=> (defn where-am-i? [] (str *ns*))
#'util/where-am-i?
util=> (ns foo (:require [util]))
nil
foo=> (util/where-am-i?)
"foo"
foo=> (ns bar)
nil
bar=> (defn ask [] (util/where-am-i?))
#'bar/ask
bar=> (ask)
"bar"
bar=> (ns foo)
nil
foo=> (util/where-am-i?)
"foo"
foo=> (bar/ask)
"foo"
foo=>
Is there some other meta data I can rely on or do I need to specify this manually?
This is not possible. In the repl, *ns* is always set to the namespace in which the repl is; at runtime it is usually clojure.core, unless someone goes to the trouble to set it, which is uncommon.
I'm not sure what your complete use case is, but judging from your example you want #'bar/ask to return its own namespace instead of returning a function that resolves the current namespace. You could simply use def instead of defn. Here is an example following on from what you did:
util=> (in-ns 'bar)
#<Namespace bar>
bar=> (def tell (util/where-am-i?))
#'bar/tell
bar=> (in-ns 'foo)
#<Namespace foo>
foo=> (refer 'bar :only '[tell])
nil
foo=> tell
"bar"
Hope this helps!

get a clojure function's code

Is there a way in clojure to get a function's code after the function has been loaded?
Ie. without doing something like [untested]
(defmacro blat [x] `(do (def code ~(quote (mexpand-all x)))
~x)))
(blat (defn func [abc] (...)))
You can get the source of a symbol using the clojure.repl/source function. However, this only works if the var for which the symbol resolves to is in a .clj file on the classpath. You can't, for example, do this:
user=> (defn foo [x] x)
#'user/foo
user=> (require 'clojure.repl)
nil
user=> (clojure.repl/source foo)
Source not found
nil