In Clojure you can only write
(.getName guild)
for JDA.
I want to get the name of this guild, but it's trying to cast it to Class from Java, instead. I cannot exactly type something like this either to my understanding:
(Guild/getName guild)
; nor this:
(Guild.getName guild)
; and at least not this:
(guild.getName)
Do anyone know what to do?
I figured it out by simply using type hinting:
(let [^Guild guild (.getGuildById jda "idHere")])
Related
I'm writing a mini-shell thing for fun, and I'm trying to define a map of commands where one of the commands is help. help should print all available commands, and I (try to) do this by looping through the keys of the commands map, but since help is part of it, no matter which order I define them in, I always get a Use of undeclared variable-warning.
How do I solve this?
(def commands {:help help})
(defn help []
(echo! "The available commands are:")
(doseq [available-command (keys commands)]
(echo! (name available-command))))
Add
(declare help)
at the beginning.
I'm trying to add some functionality to an existing JavaScript system. To be then used from JavaScript again (as opposed to within the ClojureScript namespace). Perhaps this isn't possible?
Here's a simplification of what I want to do:
// JavaScript
String.prototype.foo = function() {
return "bar";
}
# CoffeeScript
String::foo = ->
"bar"
I want to be able to run my script above, and then call it from elsewhere in the code.
I've tried messing with extend-type and defprotocol, along with export, but nothing seemed to expose my foo function.
It's possible that this was a design decision and ClojureScript isn't going to work for me here, but I just wanted to make sure I wasn't overlooking something.
It can be done like so:
(set! (.-foo (.-prototype js/String)) (fn [] "bar"))
Or you can use .. sugar:
(set! (.. js/String -prototype -foo) (fn [] "bar"))
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]))
For example, the prxml function prints XML to *out*. I would like to instead capture this output as a String. Here is the typical usage from a REPL:
user> (prxml [:p "Test"])
<p>Test</p>nil
I'd instead like to do:
(def xml (capture-out (prxml [:p "Test"])))
I made up the capture-out function, but I suspect something like it exists, only I'm having trouble finding it in the API or mailing list.
I just discovered the with-out-str from this great blog post detailing XML processing in Clojure.
So the correct implementation of my example is:
(def xml (with-out-str (prxml [:p "Test"])))
More generally, if you look at the source for with-out-str you can see how to dynamically bind *out* to any stream using binding. This works for dynamically setting the value of any existing var.