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.
Related
I'm building an application with re-frame and I'm wondering if reagent-form are meant to be used with re-frame or not, as reagent-form brings in its own way of handling state which is different than re-frame.
After experimenting a bit, I'd say it can be used, by completely ignoring the ratom that reagent-forms use for state and just using the callback, as in:
[bind-fields [form-template ...] default-values
(fn [_ _ doc]
(re-frame.core/dispatch [:update-data doc]))]
but to me, it didn't feel right, ignoring that ratom with state. That's why I created a new library called Free-form for creating forms with Reagent and optionally, with Re-frame.
Free-form doesn't store state, it just has a similar callback mechanism and it comes with a layer that makes it plugging it into Re-frame straightforward (but optional). On top of that, it makes no assumptions about the shape of your form, you are in total control of your HTML.
You can, but I think you shouldn't.
One thing you could do is just require twitter bootstrap and do some glueing to use everything in the re-frame way.
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'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 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've just started learning Clojure and I'm attempting to write something to pull some URL's from a web page into memory with some additional meta data around each URL.
I can get the URLs but it's storing them somewhere that I'm having an issue with. I've figured out I need a vector with nested maps, which I can then add new records to with assoc-in, however since I don't know the URL's I'm not sure how I go about defining my data structure initially.
So for example:
(def *comics*
[{:name "Penny-Arcade"
:url "http://www.penny-arcade.com/comic/"
:working 0
}
{:name "We The Robots"
:url "http://www.wetherobots.com/"
:working 0
}])
I'm just not sure how I start the above data structure with no data in it, then add it say initially from a command line arg, then the rest from the website.
If someone can suggest a better way that the above to store the data, please feel free.
I take it you want to modify your *comics* var from some command line argument - and then modify it even more while "working" on the elements in it.
I would suggest you don't do that.
There doesn't seem to be any reason you can't take the comics urls from the command line and pass them as arguments to a function that does the processing and returns whatever you want from those urls. Doing it that way - that is; functionally, without mutating vars - will definitely be easier to implement in clojure, easier to parallellize and just all out more idiomatic and fun.