I'm writing a mini-shell thing for fun, and I'm trying to define a map of commands where one of the commands is help. help should print all available commands, and I (try to) do this by looping through the keys of the commands map, but since help is part of it, no matter which order I define them in, I always get a Use of undeclared variable-warning.
How do I solve this?
(def commands {:help help})
(defn help []
(echo! "The available commands are:")
(doseq [available-command (keys commands)]
(echo! (name available-command))))
Add
(declare help)
at the beginning.
Related
how can I print list elements using let keyword in clojure language?
(defn build-headline-keywords-item [es-client conf common-item headline]
(let [headline headline]
(println (:headline))
(es/upsert es-client conf (merge common-item{:source ["headline"]
:type ["headline"]
:keywords headline}))))
Alan's answer covers the important parts of how to use Clojure to do this.
I'll take a different path and ask about whether this is an issue with your environment. Are you working in a REPL? Or running things in some other way? What is the actual thing you are running or evaluating?
Maybe you are using an editor where the console output is going someplace you're not seeing? For example, in Emacs the console output may go to a buffer that is not visible.
If I understand you correctly, it should look more like this:
(defn build-headline-keywords-item
[es-client conf common-item headline]
(println headline)
... )
UPDATE:
If you are still having trouble, make a test file and remove bits one-by-one until you get something that works. Then add the bits back in one at a time to build up the whole problem. It will work:
Code:
(defn build-headline [a b c headline]
(println headline))
(build-headline 1 2 3 "Space Aliens Invade!")
Result:
> lein run
Space Aliens Invade!
Please also see the online book Clojure for the Brave & True
for more information.
I am new to Clojure and Reagent. Kindly tell how to print the variable first inside the atom variable contacts?
(def app-state
(r/atom
{:contacts [{:first "Ben" :last "Lem" :middle "Ab"}]}))
First of all: the reagent tutorial is a really good place to start. It even gives you examples to solve exactly this problem.
Since reagents atom can be treated just as a regular Clojurescript atom, you can use all your normal sequence operations. Keep in mind that in order to access the current value, you have to dereference the atom via #.If you really just want to access the first :first in your atom:
(:first (first (:contacts #app-state))) or (get (first (get #app-state :contacts)) :first)
Or, if you think it's more readable
(-> #app-state
:contacts
first
:first)
I guess what you might want to do is define a few functions to make the access more easy such as:
(defn get-contacts!
"Returns the current vector of contacts stored in the app-state."
[]
(:contacts #app-state))
(defn get-first-names!
"Return a vector of all first names in the current list of contacts in the
app-state."
[]
(mapv :first (get-contacts!)))
Please keep in mind that in reagent (and in general really) you might want to dereference that atom as fiew times as possible, so look for a good place to dereference it and just use regular functions that operate on a simple sequence instead of an atom.
Still, I would really suggest you go read the aforementioned reagent tutorial.
Here is a concise way to access the value that you are looking for using Clojure's (get-in m ks) function:
(get-in #app-state [:contacts 0 :first])
Just as an extra, you may see this often written as
(->> #app-state
:contacts
(mapv :first)
first
and it's useful to understand what's going on here.
->> is a macro called thread-last which will re-write the code above to be
(first (mapv :first (:contacts #app-state)))
Thread last is a bit weird at first but it makes the code more readable when lots of things are going on. I suggest that on top of the reagent tutorial mentioned in the other comments, you read this.
#app-state will give you whatever is inside the r/atom and (:first (first (:contacts #app-state))) will return the first element and (println (:first (first (:contacts #app-state)))) will print output to the browser console (so you need to have the developer tools console open to see it).
Note that for println to output to the browser developer tools console you need to have this line in your code:
(enable-console-print!)
I've got the following problem:
I do understand that the concept of functional programming languages do not allow immutable variables, so classic variable assignment and usage like
var foo = bar();
after that in another function...
var baz = funnything(foo);
is not possible (correct me if it is, I'm still trying to get the whole idea and concepts behind functional programming).
I'm trying to play around a bit with Clojure and come to a point where I stuck:
I want to get a webpage and save the DOM into a variable for later usage.
The program starts, a prompt is spawning and the user can enter a URL which he want to fetch.
After the DOM of the website is fetched he can navigate through the DOM by for example getting the title, or all links or whatever.
The Problem:
Because I can't use a construct like
; More or less pseudo-code
(def page nil)
(get-url [url]
(page (browser/get url)))
(get-title
(println (html/select page [:title])))
I have to use the following construct:
(get-title [url]
(println (html/select (browser/get url) [:title])))
Due to this construct everytime I want to access an element of the site via get-title, get-links or whatever I have to download the whole webpage whenever the user is entering one of those methods on the command prompt.
Do I miss something here? Are there classical assigments in Clojure? Am I doing the complete thing wrong and should study a whole lot more functional programming concepts before getting hands-on and learning-by-doing?
You are misunderstanding assignment in clojure.
(page (browser/get url))
is not equivalent to: page = browser/get(url), it is equivalent to page(browser/get(url)).
I think you don't really need a global variable, just composable functions. Your example could look something like this:
(defn get-title [url]
(let [page (browser/get url)]
(println (html/select page [:title]))))
That and using memoize, like Joost mentioned, if you want to cache the return values of broser/get.
You can easily cache the value of (browser/get url) so you don't have to refetch the page every time you want to examine a property of it. See clojure.core/memoize. But that will only solve part of the problem.
In your particular case, your program requires some sort of global (or session scoped), mutable, concept of "the current page" or at least, "the current url", since that is what you're expecting your user to enter and modify. Clojure provides multiple constructs for managing mutable state.
Since you're only dealing with one page at a time, this is probably best modeled by using atoms. See http://clojure.org/atoms and http://clojuredocs.org/clojure_core/clojure.core/swap!
I'm trying to generate some Clojure code with type hints, however the type hints seem to disappear whenever I build some code (they also don't function when the code is compiled)
e.g.
`(let [^BufferedImage b (create-buffered-image)]
(.getRGB b 0 0))
=> (clojure.core/let [user/b (user/create-buffered-image)] (.getRGB user/b 0 0))
I'm not precisely sure why the type hint is disappearing, but I assume it is something to do with how metatdata is handled by the reader.
What's the right way to create correct type hints in generated code?
There are two answers to this question. To answer your specific question: in the actual code you just posted, nothing is wrong: it's working just fine. (set! *print-meta* true) and try again, and you'll see the metadata annotation. It just doesn't normally print.
But, in general this is not the right way to do things from a macro, and you will have trouble before long. Remember, you don't want metadata on the forms the macro evaluates, you want metadata on the forms the macro emits. So, a more accurate solution is to use with-meta on the symbols or forms that you want to attach metadata to - or, if they're user-supplied forms, you should usually use vary-meta so that you don't discard the metadata they added explicitly. For example,
(defmacro with-image [name & body]
(let [tagged-name (vary-meta name assoc :tag `BufferedImage)
`(let [~tagged-name (create-buffered-image)
~#body)))
(with-image i (.getRGB i 0 0))
For example, the prxml function prints XML to *out*. I would like to instead capture this output as a String. Here is the typical usage from a REPL:
user> (prxml [:p "Test"])
<p>Test</p>nil
I'd instead like to do:
(def xml (capture-out (prxml [:p "Test"])))
I made up the capture-out function, but I suspect something like it exists, only I'm having trouble finding it in the API or mailing list.
I just discovered the with-out-str from this great blog post detailing XML processing in Clojure.
So the correct implementation of my example is:
(def xml (with-out-str (prxml [:p "Test"])))
More generally, if you look at the source for with-out-str you can see how to dynamically bind *out* to any stream using binding. This works for dynamically setting the value of any existing var.