Clojure REPL and workflow - clojure

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.

Related

How to access db.clj methods in core.cljs in clojure

I am trying to create a web app in clojure.
i have used clojurescript om and react.
there are two files core.cljs and db.clj.
core.cljs contains ui for login page and db.clj contains all database connections.
Now i am trying to call a db.clj method add-user[username password] in
core.cljs.
In db.clj
(defn add-user [username,password]
(sql/with-connection db
(sql/insert-values :users [:username :password]
[username password])))
In core.cljs
(dom/button #js {:ref "submit"
:onClick (fn[e](add-user usname passwrd))}"submit")
But i am not able to call that method in core.cljs.
It shows some error message like
clojure.lang.ExceptionInfo : failed compiling file:src\login_page\core.cljs
clojure.lang.ExceptionInfo : No such namespace: login_page.db, could not locate login_page/db.cljs, login_page/db.cljc, or Closure namespace "login_page.db"
Rename db.clj to either db.cljs or db.cljc. That should get you past the 'No such namespace' error message.
That's the basic gist of it. Of course your dependencies on clj libraries will have to be removed - that might be the reason for the negative comment below. Alter your code so that you use a simple atom as your database. That should get you developing.
And you can wait for a much better answer than this one that will show you how to get the Client and Server communication setup. But it may not come because, as pointed out in the comments, there is already documentation for this, and unfortunately quite a few choices that have to be made. Another unfortunate thing is that the way to do it now may not be the way to do it early next year. Watch the Om-Next space!
I've never had any problems compiling .cljs or .cljc files. You just have to set up your lein project.clj file properly. There will be plenty of examples if you Google around, or you can take a look at the following small Github project: https://github.com/chrismurrph/passing-time - no need to worry about the code, just look at its project.clj file.

Simple runscript example with jclouds and clojure (or even just jclouds)

I have this clojure code
(let [group-name "my-test-group"
compute (compute-service provider user password)
node (create-node compute group-name)
node-id (.getId node)]
(.runScriptOnNode compute node-id ??)
(destroy-node compute node-id))
and I would like to run ls on my instance just as an example. What do I put in the ?? to make that work?
Reading the Jclouds docs it says I'm supposed to put a Statement object there but I do not know how to create a statement object for the ls command in Clojure or Java. I'd accept an example in Clojure or Java (as I can easily translate between the two).
The runScriptOnNode has several forms. As defined in the ComputeService interface, the script can be provided as a Statement object or as a simple String.
If you want to use the Statement then you can build it by using the helper methods in the Statements class (something like: Statements.exec("ls")), but it is up to you to use the Statement or the String form.
And here are the examples using the two methods (with String and with Statement) assuming the example code from the OP surrounds this code:
(.runScriptOnNode compute node-id "ls")
(.runScriptOnNode compute node-id (Statements/exec "ls"))

Enumerate namespaces and dynamically load them in ClojureScript

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.

Clojure: reload from string

EDIT: is what I want basically load-string?
Question
In Clojure, if I do:
(require :reload 'foo.bar)
then Clojure looks for src/foo/bar.clj, and reloads it.
Now, I want to do something like this:
(reload-from-string 'foo.bar STR)
the semantics of this would be: reload namespace 'foo.bar, but instead of compiling src/foo/bar.clj, compile STR instead.
How do I define reload-from-string?
Context
I need to hot reload code on a server that is running an Clojure application. I don't want to have to continuously shuffle files back & forth to the server (either via scp, sftp, or fuse/sshfs) in order to reload. Thus, I would prefer to just pass it a string.
Thanks!
You can use read-string and then eval. Keep in mind the risks though. An advantage of splitting them up is you can whitelist what is present in the resulting list before evaling it.
You probably want to bind *read-eval* to false also.

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..