In the clojure repl I can do:
=> (int \a)
97
In closurescript, I keep getting
=> (int \a)
0
In my current clojurescript project I've defined a var:
(def ord-a (int \a))
When I inspect the emitted javascript I see:
ord_a = ("a" | (0));
Which explains the discrepancy, but doesn't really do what I want. So:
What am I doing wrong here?
How do I get the ordinal/int/ascii value of a character in clojurescript?
Clojurescript does not have character literals.
As described here you can get it using js interop:
=> (.charCodeAt \a 0)
97
Related
This question already has answers here:
Why isn't my code printing like it should?
(3 answers)
Closed 2 years ago.
(defn f1 []
(for [a [1 2]]
a))
;user=>(f1)
;(1 2)
(defn f2 []
(for [a [1 2]]
(prn a)))
;user=>(f2)
;1
;2
;(nil nil)
(defn f3 []
(for [a [1 2]]
(prn a))
'something-else)
;user=>(f3)
;something-else
Why does f3 not print 1 and 2 before printing 'something-else?
i.e. I expected and had assumed (wrongly) it would print the following:
; 1
; 2
; something-else
Came across this when using a for with a lot of code inside it and this played havoc with
my attempt to use prn statements to trace the value of variables while debugging.
i.e. prn and println do not print out. I think it's only when the for block is not the
final form in its enclosing form, but i'm still not sure what's going on.
The point being that a side-effect such as prn or println, should not require to be in return value position for it to fire. So there's something deeper with list comprehensions that I don't understand.
A notion as I write this - maybe in f3 the list comprehension is simply never evaluated, due to laziness? ... oh [censored].
Yes, that is indeed it:
(defn f4 []
(doall
(for [a [1 2]]
(prn a)))
'something-else)
user=> (f4)
;1
;2
;something-else
So, even though mostly solved, I will still post this question to consolidate the learning - would anyone care to post some examples of their own gotchas re. laziness.
As you have documented here, the macro for is lazy, and doesn't execute until it has to. You can force it by wrapping it in a (vec ...) form or a doall.
For debugging purposes especially, I like to use spyx and forv from the Tupelo library to avoid all of these gotchas:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn f5 []
(forv [a [1 2]]
(spyx a))
(spy :returning :something-else))
(dotest
(spyx (f5)))
With result:
-------------------------------
Clojure 1.10.1 Java 14
-------------------------------
Testing tst.demo.core
a => 1
a => 2
:returning => :something-else
(f5) => :something-else
Ran 2 tests containing 1 assertions.
0 failures, 0 errors.
So you can see printed nicely:
the labeled value of a at each step of the forv loop.
the return value of the function with a custom label
the explicit value of the function call (f5)
nothing anywhere is lazy
spy, spyx, et al always return the value printed for further use
a convenient unit test via is= confirms the output value.
There is a nice template project that you can clone to get you started quickly.
You may also be interested in with-result, or just doseq. Don't forget the Clojure CheatSheet.
I know that there's a lot of questions about converting string to float/number/decimal... but my case is quite different cause I need to convert the string number (representing a dollar value) but I must keep the cents in this conversion, here is my case.
I receive this values
"96,26"
"1.296,26"
And I expect to convert to this follow:
96.26
1296.26
If I try to use clojure.edn it escape cents
(edn/read-string "1.296,26")
=> 1.296
(edn/read-string "96,26")
=> 96
If I try to use another approach like bugdec I get NumberFormatException
I know that we can do some string replace but it looks like a big work around, like this:
(-> "1.296,87"
(clojure.string/replace #"\." "")
(clojure.string/replace #"," ".")
(edn/read-string))
what you can do, is to use java's formatting facilities:
(defn read-num [s]
(let [format (java.text.NumberFormat/getNumberInstance java.util.Locale/GERMANY)]
(.parse format s)))
user> (read-num "1.296,26")
;;=> 1296.26
user> (read-num "96,26")
;;=> 96.26
Just use straight Java interop:
(let [nf (java.text.NumberFormat/getInstance java.util.Locale/FRENCH)]
(.parse nf "12,6")) => 12.6
See the Oracle docs: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/NumberFormat.html
and this posting: https://www.baeldung.com/java-decimalformat
You can also get a BigDecimal to avoid any rounding errors. See https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/DecimalFormat.html#%3Cinit%3E(java.lang.String,java.text.DecimalFormatSymbols)
(let [nf (DecimalFormat. "" (DecimalFormatSymbols. Locale/ITALIAN))
>> (.setParseBigDecimal nf true)
result (.parse nf "123.45,9")]
result => <#java.math.BigDecimal 12345.9M>
I would like to format a 'numeric' string as a 'string number' in Clojure. This is the format mask:
"#,###,###,##0.00"
Given the string "9999.99" I would expect to receive back "9,999.99".
How would I do this in Clojure without resorting to writing a converter function i.e. using format or something similar?
It appears that in your problem domain the disadvantages and limitations of binary-base floating point (e.g. IEEE-754) are causing you some difficulty. Perhaps you should consider taking advantage of the BigDecimal support already built in to Clojure. In Clojure, the difference between a BigDecimal constant and a floating point constant is a single character; e.g. 1.2 is a Double, while 1.2M is a BigDecimal. The bigdec function can be used to convert things to BigDecimal on the fly. For example,
(format "%,.2f" (bigdec "9999999999999999.12"))
produces
"9,999,999,999,999,999.12"
as expected. Arithmetic functions such as *, +, -, and / also work as expected.
However, this doesn't solve your basic problem. If your format string doesn't follow Java/Clojure format string conventions you'll have to write a converter function.
Best of luck.
You can use , in a format specifier:
(format "%,.2f" (float (clojure.edn/read-string "9999")))
=> "9,999.00"
(format "%,.2f" (Double/parseDouble "9999.126"))
=> "9,999.13"
Update to include bigdec example:
(format "%,.2f" (bigdec "9999999999999999.12"))
=> "9,999,999,999,999,999.12"
You can do this using NumberFormat. I also like the other answer (see the Java 10 Formatter docs for details):
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:import [java.text NumberFormat]
[java.util Locale]))
(dotest
(let [value (Double/valueOf "1234567.89")
nf (NumberFormat/getNumberInstance (Locale/US))
s1a (.format nf (.doubleValue value))
s1b (format "%,05.2f" value)]
(spyx s1a)
(spyx s1b))
s1a => "1,234,567.89"
s1b => "1,234,567.89"
(let [value (Double/valueOf "1.2")
nf (NumberFormat/getNumberInstance (Locale/US))
s1a (.format nf (.doubleValue value))
s1b (format "%,05.2f" value)]
(spyx s1a)
(spyx s1b)))
s1a => "1.2"
s1b => "01.20"
Update
Here is how to do it for BigDecimal, using first Java interop and then a built-in Clojure function bigdec:
(format "%,05.2f" (BigDecimal. "9999999999999999.12")) => "9,999,999,999,999,999.12"
(format "%,05.2f" (bigdec "9999999999999999.12")) => "9,999,999,999,999,999.12"
Question from a total newbie with Clojure. Task is pretty simple, but I'm having hard time finding the best way to do this - I need to set up input, where user could give me a list (user should determine how long) of natural numbers and the program should just return a sum of these numbers.
Maybe this is totally wrong already:
(defn inputlist[naturallist]
(println "Enter list of natural numbers:")
(let[naturallist(read-line)] ))
Here is one way of doing it:
> lein new app demo
> cd demo
Edit the project.clj and src/demo/core.clj so they look as follows:
> cat project.clj
(defproject demo "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.9.0"]
[org.clojure/tools.reader "1.1.3.1"] ]
:main ^:skip-aot demo.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
> cat src/demo/core.clj
(ns demo.core
(:require
[clojure.tools.reader.edn :as edn]
[clojure.string :as str] ))
(defn -main []
(println "enter numbers")
(let [input-line (read-line)
num-strs (str/split input-line #"\s+")
nums (mapv edn/read-string num-strs)
result (apply + nums) ]
(println "result=" result)))
with result
> lein run
enter numbers
1 2 3 <= you type this, then <enter>
input-line => "1 2 3"
num-strs => ["1" "2" "3"]
nums => [1 2 3]
result => 6
You may wish to start looking at some beginner books as well:
Brave Clojure
Living Clojure
Programming Clojure
The Clojure CheatSheet
The quickest way to do this I can think of is
#(apply + (map #(Integer/parseInt %) (re-seq #"\d+" (read-line))))
This defines an anonymous function which:
(read-line) - reads a line of text, hopefully containing numbers separated by non-numeric characters. So you type in something like "123 456 789"
(re-seq #"\d+" ...) - uses the regular expression \d+ to search for strings of consecutive digits. Each string of consecutive digits is added to a sequence, which is subsequently returned. So, for example, if you type in 123, 456, 789 the re-seq function will return the sequence '("123" "456" "789").
(map #(Integer/parseInt %) ...) - invokes the anonymous function #(Integer/parseInt %) for each element in the list returned by the re-seq invocation, creating another list of the results. So if the input is '("123" "456" "789") the output will be '(123 456 789).
(apply + ...) - applies the + function to the list of numbers, summing them up, and returns the sum.
Et voila! The end result is, you type in a string of numbers, separated by non-numeric characters, you get back the sum of those numbers. If you want to be a little neater, promote code re-use, and in general make this a bit more useful you could break this up into separate functions:
(defn parse-string-list [s]
(re-seq #"\d+" s))
(defn convert-seq-of-int-strings [ss]
(map #(Integer/parseInt %) ss))
(defn sum-numbers-in-seq [ss]
(apply + ss))
Invoking this in a Lisp-y way would look something like
(sum-numbers-in-seq (convert-seq-of-int-strings (parse-string-list (read-line))))
or, in a more Clojure-y way
(-> (read-line)
(parse-string-list)
(convert-seq-of-int-strings)
(sum-numbers-in-seq))
Best of luck.
Welcome to Clojure—and StackOverflow!
Here's how to do it:
(defn input-numbers-and-sum []
(print "Enter list of natural numbers: ")
(flush)
(->> (clojure.string/split (read-line) #"\s+")
(map #(Integer/parseInt %))
(reduce +)))
Here's how it works:
Calling print rather than println avoids printing a newline character at the end of the line. This way, the user's input will appear on the same line as your prompt.
Since there was no newline, you have to call flush to force the output buffer containing the prompt to be printed.
split splits what the user typed into a sequence of strings, divided where a regular expression matches. You have to say clojure.string/split rather than just split because split is not in Clojure's core library. clojure.string/ specifies the library. #"\s+" is a regular expression that matches any number of consecutive whitespace characters. So, if your user types " 6 82 -15 ", split will return ["6" "82" "-15"].
map calls the standard Java library function Integer.parseInt on each of those strings. Integer/parseInt is Clojure's Java interop syntax for calling a static method of a Java class. The #(...) is terse syntax that defines an anonymous function; the % is the argument passed to that function. So, given the sequence of strings above, this call to map will return a sequence of integers: [6 82 -15].
reduce calls the + function repeatedly on each element of the sequence of integers, passing the sum so far as an argument along with the next integer. map and reduce actually take three arguments; the next paragraph tells how the third paragraph gets filled in.
->> is the "thread-last macro". It rewrites the code inside it, to pass the output of each expression but the last as the last argument of the following expression. The result is:(reduce + (map #(Integer/parseInt %) (clojure.string/split (read-line) #"\s+")))Most people find the version with ->> much easier to read.
That might seem like a lot to do something very simple, but it's actually bread and butter once you're used to Clojure. Clojure is designed to make things easy to combine; map, reduce, and ->> are especially useful tools for hooking other functions together.
I've included links to the documentation. Those are worth a look; many contain typical examples of use.
There are other ways to parse numbers, of course, some of which are shown in the answers to this question. What I've written above is an "idiomatic" way to do it. Learn that, and you'll know a lot of the everyday, must-know techniques for programming in Clojure.
Yep, readline is the correct way to do it.
But each element from readlines is essentially an instance of java.lang.Character , and since you want the sum, you'd prefer to convert them to integer before summing the elements of list.
(defn input-list
[]
(print "Enter list of natural numbers")
(let [nums (read-line)]
(reduce + (map #(Integer/parseInt %) (clojure.string/split nums #"\s+")))
This might not be the most idiomatic way to do it, but feel free to tweak it.
Also, please do clean up on your variable/function names.
Edit : (Integer/parseInt %) might cause an error if used directly since the input is an instance of characters, not string. So we can use clojure.string/split to convert user input to a sequence of strings, and use Integer/parseInt % for conversion.
In fact, a more readable version can be written using thread-first macros :
(defn input-list []
(print "Enter list of natural numbers: ")
(->> (clojure.string/split (read-line) #"\s+")
(map #(Integer/parseInt %))
(reduce +)))
This is a more clojurey way to do it.
If you don't care about negative scenarios (wrong input, syntax issues), the quickest solution would be to evaluate the user's input putting it into parens:
(defn sum-ints []
(let [input (read-line)
ints (read-string (str "(" input ")"))]
(reduce + 0 ints)))
Usage:
user=> (sum-ints)
1 2 3 4 5
15
The read-string function evaluates an text expression (1 2 3 4 5) in that case. Since numeral literals turn into numbers, the result will be just a list of numbers.
I have a function encode that takes a seed and message to return a cipher.
My issue is that when I tried to use it in my core.cljs file with reagent, the function is silently failing (returning an empty string).
I feel like I'm doing something (or approach) wrong so any quick pointers will be highly appreciated.
(prn (encode "testing" "test")) ;;> ""
(prn (type encode)) ;;> #object[Function]
(prn (type (encode "testing" "jordan"))) ;;> #object[String]
For example I was expecting: "mikmbry" from (encode "testing" "test"). Everything works on the repl but silently fails on core.cljs.
Thanks for your time.
Your code has an issue with handling Strings in ClojureScript.
JavaScript doesn't have character type and ClojureScript doesn't introduce its own type. Instead when you treat a string as a sequence, it's individual elements will be one-character long strings:
(seq "ABC")
;; => ("A" "B" "C")
If you need to get the ASCII number value of a character you need to use JavaScript's String.charCodeAt(index):
(.charCodeAt "A" 0)
;; => 65
To convert a number (as ASCII code) into a string you can use String.fromCharCode:
(js/String.fromCharCode 65)
;; => "A"