Given a java package x.y.z, can I alias x.y.z to a shorter name, so that i can then refer to java classes inside the package as my-alias.MyJavaClass.
If that isn't possible, I could just import all classes into my namespace, but I don't want to specify the names of each class manually, and the clojure API docs doesn't seem clear on whether it's possible to import all classes in a package automatically.
There isn't any functionality for this (yet). Java packages are in a different namespace than Clojure's, so the usual alias tricks won't work.
What you can do is import each class, which lets you avoid the full package+class name:
(import [java.io File Writer Reader])
(new File "/")
; #<File />
Rich provides his reasons for not supporting (import [java.io.*]) here.
Related
This may actually be a bit of an XY-problem, so I'll try to explain what the goal is first.
I'm building a ClojureScript application which is composed of a set of Reagent components. It provides a user interface where you can dynamically add or remove UI elements. These UI elements (components) have a certain type. For example a Markdown component is-a Text component. Whenever the user is presented with the option to add Text we list all the components that match the type+descendants (in this case Markdown, there could be others).
The way I've coded it up is as follows.
Each component is in its own namespace, this namespace contains a builder function that returns the new component. At the root of the namespace it also calls (derive ::type ::parent)
now in some different namespace we require and enumerate all of these components in a map like:
(ns app.components
(:require
[app.gui.markdown :as markdown]
[app.gui.study-list :as study-list]))
(def all
{markdown/t markdown/builder
study-list/t study-list/builder})
Where the /t refers to the namespace-qualified keyword which was used to define the hierarchy. We use the all map to provide the data for the menu's that face the user (which components can be added, filtered by type).
Now, as you can imagine, this isn't pretty. Since it must now maintain such a (potentially) long list of all the types in the hierarchy manually.
Rather I would do something like (def all (components-of (descendants ::root))) but I'm unsure how to tackle this, since I think it would require finding vars by name (not supported in ClojureScript).
So my question is: how do you maintain a map or list of namespaces + vars (dynamically) in ClojureScript?
You cannot do this dynamically, but as far as I can tell for your problem there isn't much need. ClojureScript macros can reflect back into the compiler - you could easily use the cljs.analyzer.api namespace to figure out which vars you need (through var metadata or whatever) and automatically emit the runtime info map you want. This is in fact very similar to how cljs.test/run-tests works. It uses the compiler to filter out all vars in all namespaces with :test metadata attached and it generates the code to test each one. It's worth examining cljs.test in detail to see how this can be done.
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.
I have written two modules m1.py and m2.py each of which uses various modules from the standard library.
For example
#m1.py
import sys
#.
#.
and
#m2.py
import os
#.
#.
What "bothers" me is that when I import in main.py the two modules m1.py and m2.py
I can use the functions defined in sys and os like this:
#main.py
print m1.sys.version
print m2.os.listdir()
Is this normal, or there is something I should consider when importing modules in my code?
Usually you don't need to worry about what is accessible in your namespace. Anyone who messes around with stuff that's not part of the module's documented API deserves whatever trouble they get. Python assumes that it's programmers are responsible adults.
The exception is when you specifically want to allow other code to use the otherwise discouraged from mymodule import * syntax. Then you want to limit what is public, so that you don't clutter up your importer's namespaces with your own internal stuff.
Here's how you can do that:
Names that begin with an underscore (e.g. _foo) are assumed to be private, and won't be imported with from mymodule import *. This isn't "real" privacy, as anyone who does a normal import will still be able to access them via mymodule._foo (but they probably shouldn't!).
If you want to make the modules you're importing private, use an as clause to give them a "private" name as described above. That is, use import os as _os.
Or, rather than messing around with underscores, you can create an __all__ variable that explicitly lists the module's public names. Only the names in the list will be imported with a from mymodule import * statement. Note that an __all__ sequence is required in packages if you want the submodules to be importable via from mypackage import *. That's because Python can't trust the filesystem not to mess with the capitalization of the filenames the package contains.
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..
I have created a record like this:
(defrecord User [user-id email])
:but when I try to access it from another name-space I get the error:
(User. "name" "email")
java.lang.IllegalArgumentException: Unable to resolve classname: User
It works when I do:
(oe.model.modelcore.User. "name" "email")
: I know I will need to import the Java class, but is there any way for clojure to do this automatically when I do:
(use 'oe.model.modelcore :reload)
Technically you must require it (don't necessarily need to use it) so that the file containing the record definition is compiled and the class is created. Then you must import it so that it is available to construct as a Java class. If you create a constructor function in the first ns like
(defn new-user [id email]
(User. id email))
then you will not need to import it in the calling ns.
I wrote this up a while back here:
http://tech.puredanger.com/2010/06/30/using-records-from-a-different-namespace-in-clojure/
It could be really tricky if you have - (dash) in your name space.
As it turns out there were two errors:
– Importing defrecord from another namespace is not just :use. I had to first :require the namespace, then import the defrecord. This was a trivial problem to solve and I figured it out quickly. Only this did not work in my case
– Dashes “-” and Underscores “_” are a nuisance since we are mixing Lisp with Java. While the file system uses underscores Clojure converts things to dashes. Brilliant.
So to fix the second error I use the follow in the ns block
(ns adder.core
(:require building-blocks.activity)
(:import [building_blocks.activity Activity]))
https://cyrax.wordpress.com/2013/07/22/clojure-importrequireuse-defrecord-from-another-namespace/
In your question you are creating a record, then invoking the constructor for the class generated as a side effect. To do so you need to import that class as mentioned in another answer.
However, imho the preferred path (since Clojure 1.4) is to use the constructor functions generated by defrecord (here they'll be named ->User and map->User). These functions allow you to avoid the interop forms and just refer in the constructor functions like any other function. By avoiding interop, this is a more portable less-hosty solution:
(ns some-ns
(:require [oe.model.modelcore :refer (->User)]))
(def user (->User "name" "email"))
You have to import the record like this:
(ns some-ns
(:import [oe.model.modelcore User]))