ClojureScript format string with goog.string.format doesn't substitute - clojure

I'm trying to format a color in hex for use in HTML, running ClojureScript in the browser.
Here's my "format" function.
(defn gen-format [& args] (apply gstring/format args) )
in a "strings" namespace where I've required the goog.string library with :
(:require [goog.string :as gstring] [goog.string.format :as gformat])
But when I try to call it from javascript :
document.write(mypackage.strings.gen_format("#%x%x%x",0,0,0));
it just returns #%x%x%x
It's not crashing. But the goog format function doesn't seem to be substituting the values in. Am I doing something wrong here?

What does %x do?
Looking at format source sorce, it only supports s, f, d, i and u:
var formatRe = /%([0\-\ \+]*)(\d+)?(\.(\d+))?([%sfdiu])/g;
This seems to be working well for me:
mypackage.strings.gen_format("#%d%d%d", 0, 0, 0)
UPDATE: If you need to render a string with color, how about these:
(defn hex-color [& args]
(apply str "#" (map #(.toString % 16) args))
(defn hex-color [r g b]
(str "#" (.toString r 16) (.toString g 16) (.toString b 16))

Related

Clojure: First Function and Tick Marks

(ns main.core)
(defn andexp [& resty]
(println "here is resty:" resty)
(first (resty))
)
I am very new to Clojure coming from a Java and C background
In the repl, the input has to be in this format:
(andexp '(John is a beginner so have mercy))
I need to include the tick mark ('). I want my program to print out "John."
There are two things happening here:
You are using & resty to destructure for a list of all the arguments; that is why you see the output of ((John ...)) (note the double (()).
Next you are calling resty, when you write (resty), which results in an error (remember, parens in clojure are always meaningful and not just for groupting things togehter etc. like in curly braces languages).
So this will do what you want:
repl=> (defn andexp [resty]
(println "here is resty:" resty)
(first resty))
#'repl/andexp
repl=> (andexp '(a b c))
here is resty: (a b c)
a
If you really want to destructure (like stated in the comments), you have to put your arguments into another pair of [] to destructure on the passed in list. E.g.
repl=> (defn andexp [[f & resty]]
(println "here is f and resty:" f resty)
(first resty))
#'repl/andexp
repl=> (andexp '(a b c))
here is f and resty: a (b c)
b
More infos about
destructuring
If you write it like so:
(defn andexp
[& resty]
(println "here is resty:" resty)
(first resty))
you will get a result:
(andexp '(John is a beginner so have mercy)) #=>
here is resty: ((John is a beginner so have mercy))
(John is a beginner so have mercy)
but you probably wanted something more like this:
(defn andexp
[& resty]
(println "here is resty:" resty)
(first resty))
(println :result (andexp 1 2 3 4) ) ; no wrapping parens
with result:
here is resty: (1 2 3 4)
:result 1
Another option:
(defn andexp
[& resty]
(println "here is resty:" resty)
(first (first resty))) ; or `ffirst`
(println :result (andexp [1 2 3 4]) )
with result:
here is resty: ([1 2 3 4])
:result 1
It may help to clarify the answer if you add more info about the use-case or goal.
For background, please see the documentation listed here:
https://github.com/io-tupelo/clj-template#documentation

clojure.lang.LazySeq cannot be cast to java.lang.CharSequence

I am writing a function that, for any given string, replaces any digits within that String with the same number of '.' characters.
Examples:
AT2X -> AT..X
QW3G45 -> QW...G.........
T3Z1 -> T...Z.
I've written the following Clojure function but I am getting an error I don't quite understand:
java.lang.ClassCastException: clojure.lang.LazySeq (in module: Unnamed Module) cannot be case to java.lang.Charsequence
I'm interpreting from the error that I need to force an evaluation of a lazy sequence back into a String (or CharSequence) but I can't figure out where to do so or if this is correct.
(defn dotify
;;Replaces digits with the same number of '.'s for use in traditional board formats
[FEN]
(let [values (doall (filter isDigit (seq FEN)))]
(fn [values]
(let [value (first values)]
(str/replace FEN value (fn dots [number]
(fn [s times]
(if (> times 0)
(recur (str s ".") (dec times)))) "" (Character/digit number 10)) value))
(recur (rest values))) values))
There is a standard clojure.string/replace function that may handle that case. Its last argument might be not just a string or a pattern but also a function that turns a found fragment into what you want.
Let's prepare such a function first:
(defn replacer [sum-str]
(let [num (read-string num-str)]
(apply str (repeat num \.))))
You may try it in this way:
user> (replacer "2")
..
user> (replacer "9")
.........
user> (replacer "22")
......................
user>
Now pass it into replace as follows:
user> (clojure.string/replace "a2b3c11" #"\d+" replacer)
a..b...c...........
Here's a way to do this using reduce:
(defn dotify [s]
(->> s
(reduce (fn [acc elem]
(if (Character/isDigit elem)
(let [dots (Integer/parseInt (str elem))]
(apply conj acc (repeat dots \.)))
(conj acc elem)))
[])
(apply str)))
(dotify "zx4g1z2h")
=> "zx....g.z..h"
And another version using mapcat:
(defn dotify-mapcat [s]
(apply str
(mapcat (fn [c]
(if (Character/isDigit c)
(repeat (Integer/parseInt (str c)) \.)
[c]))
s)))
There are some issues in your example:
Many of the internal forms are themselves functions, but it looks like you just want their bodies or implementations instead of wrapping them in functions.
It's hard to tell by the indentation/whitespace, but the entire function is just recur-ing, the fn above it is not being used or returned.
One of the arguments to str/replace is a function that returns a function.
It helps to break the problem down into smaller pieces. For one, you know you'll need to examine each character in a string and decide whether to just return it or expand it into a sequence of dots. So you can start with a function:
(defn expand-char [^Character c]
(if (Character/isDigit c)
(repeat (Integer/parseInt (str c)) \.)
[c]))
Then use that function that operates on one character at a time in a higher-order function that operates on the entire string:
(apply str (mapcat expand-char s))
=> "zx....g.z..h"
Note this is also ~5x faster than the examples above because of the ^Character type-hint in expand-char function.
You can do this with str/replace too:
(defn expand-char [s]
(if (Character/isDigit ^Character (first s))
(apply str (repeat (Integer/parseInt s) \.))
s))
(str/replace "zx4g1z2h" #"." expand-char)
=> "zx....g.z..h"

"Unbound" variables in clojure functions

I'm writing a function to parse out IRC RFC2813 messages into their constituent parts. This consists of two functions, one to split the message via regex, and another to modify the return to handle certain special cases.
(let [test-privmsg ":m#m.net PRIVMSG #mychannel :Hiya, buddy."])
(defn ircMessageToMap [arg]
"Convert an IRC message to a map based on a regex"
(println (str "IRCMapifying " arg))
(zipmap [:raw :prefix :type :destination :message]
(re-matches #"^(?:[:](\S+) )?(\S+)(?: (?!:)(.+?))?(?: [:](.+))?$"
arg
)
)
)
(defn stringToIRCMessage [arg]
"Parses a string as an IRC protocol message, returning a map"
(let [r (doall (ircMesgToMap arg))])
(println (str "Back from the wizard with " r))
(cond
;Reformat PING messages to work around regex shortcomings
(= (get r :prefix) "PING") (do
(assoc r :type (get r :prefix))
(assoc r :prefix nil)
)
;Other special cases here
:else r)
)
The problem I'm running into is that the stringToIRCMessage function doesn't appear to be realizing the return value of ircMesgToMap. If I evaluate (stringToIRCMessage test-privmsg), the println statement gives me:
Back from the wizard with Unbound: #'irc1.core/r
..but the "IRCMapifying" result from ircMessageToMap appears on the console beforehand indicating that it was evaluated correctly.
The doall was an attempt to force the result to be realized in the middle of the function - it had no effect.
How should I rewrite this stringToIRCMessage function to get the r variable usable?
The parens are wrong in your let statement.
Should look like this:
(let [r (doall (ircMesgToMap arg)) ]
(println (str "Back from the wizard with " r))
(cond
;Reformat PING messages to work around regex shortcomings
(= (get r :prefix) "PING") (do
(assoc r :type (get r :prefix))
(assoc r :prefix nil)
)
;Other special cases here
:else r))

lein run, won't run -main correctly, though a clean nrepl will

New to clojure, trying to compile the following code, for a boolean expression evaluator
;core.clj
(ns my-app.core
(:gen-class))
(defn t [& args] (if (empty? args) t
((first args) t (first (rest args)))))
(defn f [& args] (if (empty? args) f
((first args) f (first (rest args)))))
(defn | [cond1 cond2] (if (= cond1 t) t
(if (= cond2 t) t f)))
(defn & [cond1 cond2] (if (= cond1 f) f
(if (= cond2 f) f t)))
(defn ! [& args] (if (= (first args) t)
(apply f (rest args))
(if ( = (first args) f)
(apply t (rest args))
(! (apply (first args) (rest args))))))
(defn -main [& args]
(loop [line (read-line)]
(do
(println (eval (read-string (apply str "" (interpose \space (seq (str "(" line ")")))))))
(if (= (count line) 1) nil (recur (read-line))))))
Everytime I do "lein run" and enter the string "(t|t)=t" I get the following error
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: t in this context
However If I open up a new nrepl in the "src/my_app/" dir, and enter the command
(-main)
I get the correct string and result
( ( t | t ) = t )
true
I should note, that while running lein run
the other strings string "+ 1 2 3 4 5 6" will evaluate correctly, but for some reason it won't recognize the function (t ...)
Anybody have any ideas what's going on?
eval uses the current (thread-bound) value of *ns* to determine what namespace you're currently "in", which controls how unqualified symbols are resolved. At the repl after running (ns my-app.core ...), you're in the my-app.core namespace and thus eval finds the t you've defined there. However after compilation even though you still defined t in my-app.core, when your program begins running you're in the user namespace and eval fails to find t.
So all you need to do is change your namespace within -main to be my-app.core, using binding like this:
(defn -main [& args]
(binding [*ns* (the-ns 'my-app.core)]
(loop [line (read-line)]
(println (eval (read-string (apply str (interpose \space (str "(" line ")"))))))
(when-not (= (count line) 1)
(recur (read-line))))))

How to find the width and height of an image with quil in clojure

I am trying to find the width of a loaded image in clojure. In processing I would do this,
PImage img=loadImage("image.jpg");
int x=img.width;
int y=img.height;
I tried to do this same in clojure but it won't work
(defn loadwebimg []
(let [filelst (map (fn [f] (.getName f)) (.listFiles (File. (str datadir))))
imgf (first (shuffle filelst))
webimg (load-image (str datadir imgf))
]
(image webimg 0 0)
(println webimg.height))
If webimg is an object when you would use the . special form to read its fields like you do for the file objects you use above it.
as user100464 points out:
(println webimg.height)
would become
(println (. webimg height)
or
(println (.height webimg))