Clojure - require several versions of a library in a project - clojure

Everything is in the title, but here is an example use case :
a function had a first parameter like the following :
(my-fn "a.b.c" ...)
Which now in a newer version became :
(my-fn ... ["a", "b", "c"])
Is it possible to :require a specific version of a library ?
For instance :
:require my.util.lib :as newlib ;; new version
:require my.util.lib#v0.0.1 :as lib ;; old library
It would then allow to migrate this library usage file per file.

As mentioned in the comments, I think Osgi is the only true way to accomplish this, and probably not worth the effort in complexity to set it up.
What are the versions of the library you are using? If it is following semantic versioning practices, and it still on a version with breaking changes, you have to be prepared for this sort of thing and will probably just have to update your code.

Related

Make clojure functions available in every namespace during development?

I have number of useful helper functions that I use at the REPL during Clojure development. This includes some built-in functions like doc and pprint, but also some custom ones of my own from my user.clj. The default clojure experience seems to be:
dev> (doc +)
;; works
dev> (in-ns 'project.core)
project.core> (doc +)
;; what is this "doc" thing you're talking about!?!?
which is pretty irritating (I'm aware that I can refer to clojure.repl/doc here). Is there an easy way to ensure that something is available during development regardless of which namespace I'm currently operating in?
One option is to add a :repl-options to your project map in project.clj:
(defproject myproj "1.0"
:dependencies [[org.clojure/clojure "1.9.0-alpha15"]]
:repl-options { :init-ns myproj.core
:init (require '[clojure.repl :refer :all]) })
...
$ lein repl
myproj.core=> (doc +) ; works
As Alex Gherega mentions, it's probably a bad idea to automatically and indiscriminately import stuff into every namespace. However, you could create a macro (or maybe a function would work?) to help import development-related namespaced when/if they are needed. Add it to your user.clj. Then if you are working in another namespace and decide it would be useful, you can just run (user/import-useful-dev-stuff) (or whatever you decide to call it).
For what it's worth, I pretty much do all my REPL sessions within the user namespace and require all the namespaces I need from there. I use Emacs, and if I need to change something in another namespace, I just change the source, then do C-c C-k (after initiating a cider session) to reload the file. If you don't use Emacs, it's only a little more work to reload from the REPL via require with the :reload option.
Unless you use boot or lein or some other form that would "magically" add this namespace to your REPL development session then I'm afraid you're just have to require it by hand every time.
The thing is namespaces have their well intended role of avoiding name conflicts. If you would have another way of telling a current namespace to use/require another namespace without doing it then you would have a whole lot of other problems.
If you're not using lein/boot you could just do as Alex Miller responded. For a more controlled way of what you need from the clojure.repl or some other ns API just have a require & use declaration in you namespace of interest e.g.:
(ns 'project.core
(:require [clojure.repl :refer [doc]]))
If you get yourself in this situation, do:
(clojure.core/refer-clojure)
to require and load everything from clojure.core.
Or an alternate approach, if project.core exists, is to instead:
(require 'project.core)
(in-ns 'project.core)
Loading the namespace via require will refer clojure.core.
Or if project.core does not exist, do:
(ns project.core)
The ns macro will do both refer-clojure and in-ns.

Running seesaw and overtone libraries in clojure

I want to use the overtone and seesaw namespaces in one project. However when i load them there seems to be a shared function named (select) which exists in both seesaw.core and overtone.core ((seesaw.core/select) (overtone.core/select)), why i can't load both of the namespaces in the project. How could i come up with this? Will using refer with the :exclude keyword an option?
While many tutorials and examples use the use function or the :use clause in the ns form, in real code it is better to never do this. The preferable form is as follows:
(ns foo.bar
(:require [a.something :as some]
[b.another :as a]))
(some/f)
(a/f)
The functions are fully distinct and unambiguous, and also this makes the code easier to read and refactor - you have a clear indication of where the definitions you are using come from.

Dealing with resources (copying) when building a ClojurScript project using leiningen

I have just begun playing with ClojureScript and I'd like to collect all CSS files into a single folder (out/css). I found leiningen-less and with the following config I get the compiled CSS files into the correct location:
:less {:source-paths ["src/less"]
:target-path "out/css"}
I can't find any documentation on how I can handle the ordinary CSS files (e.g. the file for resetting defaults, css/reset.css). Basically I want the equivalent of cp css/*css out/css.
I did find lein-resource but it does a bit more than I require (pass things through stencil) and more importantly it through an UnsupportedOperationException on my with what I thought would a be a valid configuration:
:resource {:resource-paths ["css" {:target-path "out/css"}]}
Please englighten me!
For your particular use case just rename reset.css to reset.less. less should be able to read CSS without problems.
For more advanced frontend tooling maybe consider adding something like make/grunt/etc. More complexity but more power & flexibility.
I think better and easy solution would be that you write a function that uses clojure.java.io library functions and integrate them with lein-less "compiler" fork, so this is my internal function proposal:
(defn your-fn[]
(remove-folder "./out") ;; => you have to do how to make that fn following io lib doc
(copy-folder "./css ./out") ;; ;; => you have to do how to make that fn following io lib doc
(run-compiler :javascript
{:project-root "your-project-root/"
:source-paths ["less"]
:target-path "out"})))
PS: note that you need to call this fn from your clojurescript compilation process, BTW I didn't know if there is a way for that :)

Clojure warning: "resultset-seq already exists in clojure.core"

I'm new to Clojure and building a web app using the Noir framework (very similar to Compojure, in fact I think it's Compojure with a different request handler layer). I'm getting a warning when I import the JDBC library:
WARNING: resultset-seq already refers to: #'clojure.core/resultset-seq in namespace: webapp.models.database, being replaced by: #'clojure.java.jdbc/resultset-seq
Do I have to live with this warning or is there a way around it? I'm importing the JDBC library using:
(use 'clojure.java.jdbc)
You can avoid the problem by specifying the exact bindings to be imported:
(use '[clojure.java.jdbc :only [insert-values transaction]])
(transaction
(insert-values ...))
Another option is to :exclude the offending binding:
(use '[clojure.java.jdbc :exclude [resultset-seq]])
(transaction
(insert-values ...))
You can also just use require instead:
(require '[clojure.java.jdbc :as db])
(db/transaction
(db/insert-values ...))
With regard to forward compatibility, require is arguably safest. Using :only is just slightly less clean but still a pretty good approach (and easy to fix when it breaks). Excluding the currently offending bindings is probably the least future-proof way of fixing the problem since other conflicting bindings can appear at any time and tracking down what is imported from where can be tricky.
There are lots of options. What this warning means is, that you are replacing an already defined symbol with a definition from different package. In this case, it looks like this is a variable that you've defined, right? If so the easiest solution might be to just rename it in your code.
Or if you don't need the resultset-seq from clojure.java.jdbc package you can exclude it:
(use '[clojure.java.jdbc :exclude (resultset-seq)])
or better yet,
(use '[clojure.java.jdbc :only (f1 f2 f3)])
where f1, f2, f3 are the things you're actually need.
(use '[clojure.java.jdbc :as jdbc])
and then use jdbc/resultset-seq
Or you can just:
(require 'clojure.java.jdbc)
and then use clojure.java.jdbc/reusltset-seq
In addition to the other excellent answers, if you want the jdbc resultset-seq instead of the core one, you can exclude the latter from being brought into the current ns:
(ns foo
(:refer-clojure :exclude [resultset-seq])
(:use clojure.java.jdbc))

emacs completions or IntelliSense the same as on Visual Studio

emacs 22.2.1 on Linux
I am doing some C/C++ programming using emacs. I am wondering does emacs support completions (IntelliSense in Visual Studio).
For example when filling structures I would like to see the list of members when I type the dot operator or arrow operator.
The same would go for function signatures that give me the types I am passing would display.
Meta-/ isn't exactly intelligent, but it does iterate through known names.
This project provides the dropdown style menus you're used to:
http://ecb.sourceforge.net/
you need to take latest version of CEDET package (better, directly from CVS). You can setup it, as described in documentation on this site
I am using cedet with emacs. I tried using the cedet version in Debian but it has some bugs so I uninstalled that and downloaded the cvs version from http://sourceforge.net/projects/cedet/develop
I compiled it in my ~/tmp/emacs-stuff/ directory and then added the following lines to my ~/.emacs.d/custom.el file:
;;needed if cedet is in a custom location
(load-file "~/tmp/emacs-stuff/cedet/common/cedet.el")
;; Enable EDE (Project Management) features
(global-ede-mode t)
;;to enable code folding
(global-semantic-tag-folding-mode)
;; Enabling Semantic (code parsing, smart completion) features
;; (select only one)
;;(semantic-load-enable-minimum-features)
;;(semantic-load-enable-code-helpers)
(semantic-load-enable-gaudy-code-helpers)
;;(semantic-load-enable-all-exuberent-ctags-support)
(global-semantic-idle-scheduler-mode 1) ;The idle scheduler with automatically reparse buffers in idle time.
(global-semantic-idle-completions-mode 1) ;Display a tooltip with a list of possible completions near the cursor.
(global-semantic-idle-summary-mode 1) ;Display a tag summary of the lexical token under the cursor.
;;to work with my include files and cedet
(semantic-add-system-include "~/include" 'c++-mode)
(semantic-add-system-include "~/include" 'c-mode)
;;To use additional features for names completion, and displaying of information for tags & classes,
;; you also need to load the semantic-ia package. This could be performed with following command:
(require 'semantic-ia)
;;to work with systme include files and gcc
(require 'semantic-gcc)
;;integrate semantic with Imenu
(defun my-semantic-hook ()
(imenu-add-to-menubar "TAGS"))
(add-hook 'semantic-init-hooks 'my-semantic-hook)
;;load Semanticdb
(require 'semanticdb)
;;(global-semanticdb-minor-mode 1)
;;working with tags
;; gnu global support
(require 'semanticdb-global)
(semanticdb-enable-gnu-global-databases 'c-mode)
(semanticdb-enable-gnu-global-databases 'c++-mode)
;; ctags
(require 'semanticdb-ectag)
(semantic-load-enable-primary-exuberent-ctags-support)
(defun my-semantic-hook ()
(imenu-add-to-menubar "TAGS"))
(add-hook 'semantic-init-hooks 'my-semantic-hook)
This file gets called by my ~/.emacs file which the following line in it:
(load-file "~/.emacs.d/custom.el")
Now when you are typing a variable and press CTRL+SHIFT+ENTER, a menu of selections will come up with suggestions.
Further, if you have set semantic-complete-inline-analyzer-idle-displayor-class variable to quote semantic-displayor-tooltip, a tooltip with suggestions will also come up after some idle time (1 or 2 seconds).
For some short intro, see http://xtalk.msk.su/~ott/en/writings/emacs-devenv/EmacsCedet.html
For Cedet docs, see: http://cedet.sourceforge.net/
Good luck.
I think you're looking for etags.
http://tulrich.com/geekstuff/emacs.html
Search for TAGS.
If you'd like to use stock emacs to do completion from your project and library include files try this answer
I have this in my .emacs, which makes things a bit easier.
(require 'c-eldoc)
(add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)
This way, I don't have to look up function definitions.
I don't write that much, but I agree that TAGS are also a very useful feature.