Octal number handling in Clojure

503 views Asked by At

I'm trying to create an octal handling function in Clojure, so far I have this:

(defn octal [a]
    (if (= 023 a) 
      (Integer/toOctalString a)
      a))

where I have '023' i would like to replace it with some logic which checks if a number begins with '0'. I'm aware of starts-with? for strings, is there a method for use with numbers?

I'm trying to do it this way as if I pass Integer/toOctalString an integer without a 0 it passes back a larger number. E.g. 2345 becomes 4451.

Thank you

2

There are 2 answers

0
Sylwester On

It seems read-string can do this for you:

(read-string "023")
; ==> 19

(read-string "19")
; ==> 19

If you want to read octal without prefix you can simply add the zero before passing it:

(defn octal->integer [s]
  (read-string (str \0 s)))

(octal->integer "23")
; ==> 19
0
Arthur Ulfeldt On

When outputting numbers:

The built in format function does this nicely:

user> (format "%o" 19)
"23"

of course nothing about a number knows if it was originally provided in a particular format, though if you put it into a collection and store that information along with it, either directly or in metadata you can keep track of that.


As far as reading numbers is concerned:

Clojure numbers are Octal by default if they start with a leading zero

Just the usual warning that clojure.core/read-string IS TOTALLY UNSAFE to use on untrusted input. It will run code from the string at read time if not carefully managed.

user clojure.edn/read-string instead

They both will read an octal number for you just fine:

user> (clojure.edn/read-string "023")
19
user> (read-string "023")
19

And clojure.edn/read-string will refuse to p0wn your server:

user> (read-string "#=(println \"Pwning your server now\")")
Pwning your server now
nil

user> (clojure.edn/read-string "#=(println \"Pwning your server now\")")
RuntimeException No dispatch macro for: =  clojure.lang.Util.runtimeException (Util.java:221)

So it's worth being in the habit of using clojure.edn for all data that it not actually part of your program.


PS: there is a dynamic var you can set to turn off the reader-eval feature of read string, and depending on it is an accident waiting to happen.