Leiningen: How to define constants in project.clj? - clojure

I have some values repeated in my project.clj like below:
(defproject foo "0.1.0-SNAPSHOT"
...
:dependencies [[bar "3.4.5"]
[baz "3.4.5"]
[bat "3.4.5"]]
...)
I would like to use some sort of constant here so, when these libraries get updated to 3.5.0 for example, I have to change just one place.
What is the best practise here? Best I can come up with is this:
(def deps-version "3.4.5")
(defproject foo "0.1.0-SNAPSHOT"
...
:dependencies [[bar ~deps-version]
[baz ~deps-version]
[bat ~deps-version]]
...)

Using a definition before defproject is totally fine and common practice.
You can also so more advanced stuff like depending on the build environment (I would tag the effective project version too that case). A nice example is found in the answers to this question "Leiningen: How to define constants in project.clj?"

Related

How to properly set a timezone in a clojure REPL?

When running a query on a postgres database on a clojure REPL, the timestamps fields are presented in UTC and I need them to be in timezone America/Sao_Paulo (UTC-3)
So far I have tried the following on Intellij's REPL:
Set -Duser.timezone=America/Sao_Paulo inside the file idea.vmoptions (intellij's)
Add :jvm-opts ["-Duser.timezone=America/Sao_Paulo"] to project.clj
Add -Duser.timezone=America/Sao_Paulo in Intellij's REPL configuration
export JAVA_OPTS="-Duser.timezone=America/Sao_Paulo:$JAVA_OPTS" inside ~/.zshrc
and the following on Leiningen REPL:
Add :jvm-opts ["-Duser.timezone=America/Sao_Paulo"] to project.clj
export JAVA_OPTS="-Duser.timezone=America/Sao_Paulo:$JAVA_OPTS" inside ~/.zshrc
None worked so far!
Sample code
(ns experiments
(:require [next.jdbc :as jdbc]))
(def db
{:dbtype "postgres"
:dbname "<dbname>"
:host "<host>"
:port 5432
:user "<user>"
:password "<pass>"})
(def ds (jdbc/get-datasource db))
(jdbc/execute! ds ["select current_timestamp"])
You did not mention any Postgres options. Please study this page carefully for info and options.
If the above does not solve your problem, it may be easiest to use java.time to do the conversion. I also have some helper/convenience functions available here. Unit tests show them in action, and the source code provides examples of java.time interop from clojure.
I would avoid the older Joda Time libraries as they are obsolete (replaced by java.time). I think that Java interop is the easiest & most straightforward way to access java.time.

printing list values using let in clojure

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.

Clojure REPL and workflow

Coming from Haskell, my usual workflow would be to :l <file name.hs> on ghci and use the functions and ADT that I have there.
Right now I am using lein repl on a typical lein new app project context. I have created a testing.clj file next to my core.clj. There I defined a couple of functions, a protocol and a record implementing the protocol. I was able to use the function by (use 'testing.testing :reload) the problem is that I am not able to use the actual record:
(def c (Something. 0))
I get:
CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: Something
So, what would be the a "better" workflow in this case? Where I don't want to set the functions, protocols, records directly on the REPL, but also I don't want to rely on my core.cls file? I just want a file where I can dump a bunch of stuff and play with it.
PS: My env is Mac OSX Terminal + Sublime
Edit: After a couple of minutes I was able to load the record by:
(load-file <file name>)
(import 'testing.testing.Something)
I mean, for sure there is a better way than this... :/ I just want to load everything. On the other hand I am able to use the protocol methods the record implements.
Have you tried using the convenience function that is automatically defined for creating records? In this example it would be (->Something 0).
(Something. 0) is using the Java constructor, which requires importing the Java class separately. The Java class is created automatically when you define a record to allow Java interop with things you've defined in Clojure.
Using the (->Something 0) syntax is the correct way to go and should be possible after you (use 'testing.testing :reload).
Edit Given the above didn't seem to help, here's some step-by-step instructions to get a minimal working example
You have an app directory testing created with lein new app testing
In testing/src/testing you create testing.clj containing the following two lines
(ns testing.testing)
(defrecord Something [n])
Run lein repl from within your project directory
Use the namespace with (use 'testing.testing :reload)
(:n (->Something 42)) will create an instance of Something and retrieve the value of its n member - in this case 42.

How do I compile Clojurescript forms from within Clojure?

I am using clj-webdriver to do some Selenium based testing on a Clojurescript web app. Sometimes, there is something in the app itself that I want to be able to fiddle with while the test are running. I see that clj-webdriver has something called (execute-script js args) that takes a string of Javascript code and runs it on the current testing browser. I have tested this and it seems to work. I would like to pass clojurescript code to execute-script though. I need something that will compile my Clojure form into Clojurescript code.
I see the following question that sort of relates. It says to use the js/emit function from clutch. I searched clutch and found it mentioned only in (view) in cljs-views.clj I have attempted the following in a repl:
user> (use 'com.ashafa.clutch.cljs-views)
nil
user> view
<core$comp$fn__4034 clojure.core$comp$fn__4034#ebd3f80>
user> js/emit
CompilerException java.lang.RuntimeException: No such namespace: js, #compiling (NO_SOURCE_PATH:1)
user>
This isn't terribly surprising, how could js be in a regular clojure namesapce? But how do I use this (or any other) system to generate Clojurescript (javascript) code that I can pass to execute-script?
Use the cljs.closure/build function:
(use '[cljs.closure :only [build]])
(build '(print "hello") {:optimizations :simple :pretty-print true})
There are more examples in a comment at the bottom of closure.clj. There are options for outputting to a file as well.

What are the namespace gotchas for clojurescript when coming from clojure?

I'm trying to understand the namespacing model in clojurescript. I understand that javascript doesn't come built in with namespace support, so its been an add on via the google closure library. However, I don't understand how clojurescript deals with these differences. Can someone please explain?
Lets say for example I want to use the google charts api and whenever possible would like to use advanced compilation. What do I use in the closure/build call, how would the ns form look like and what's the best way to refer to the api from the code? I've looked at https://github.com/sritchie/contour but that example doesn't use advanced compilation, and I don't see the options referring to the google api in the project.clj file.
The namespace declaration is the same regardless of whether you are using simple or advanced mode compilation. The difference is that libraries that don't participate in google dependency management via goog.require('') and goog.provide('') need to be explictly referenced via an externs.js file. This file, which you pass to the cljs compiler, provides stubs of all the vars and associated methods. A typical externs.js would look something like:
// contents of externs.js
var externalLibrary = {}
var externalLibrary.method = function() {}
So to reference a google closure aware library your namespace declaration looks like this:
(ns my.namespace
(:require [goog.events.KeyCodes :as key-codes])
And that emits the following javascript:
goog.provide("my.namespace");
goog.require("goog.events.keycodes");
Note that if you want to call your closurescript from another javascript file then you need to tag the method as exported so that the optimizing compiler knows to preserve the name. (e.g. you might have a script tag on a page from where you want to call a javascript function that has been generated from clojurescript)
That looks like this:
(defn ^:export externallyCalled [])
The other thing to be aware of is that you have to treat macros differently in clojurescript, this is because the ability to process them 'on the fly' in the reader is not present in the same way as it is in clojure.
you do that as follows (note that you are obliged to bind the macros with :as in this case)
(ns my.namespace
(:require-macros [my.macros :as my]))
If you are calling code that didn't participate in google's dependency management you access it via the js namespace and the javascript interop...
(. js/nonGoogle (method args)) ; a method access
(. js/nonGoogle -p) ; a property access
all the usual . variants work too..