12
votes

I'm trying to pull an integer out of localStorage with a simple clojurescript app. Everything I've tried ended up trying has some sort of wrong behavior.

Below is my program without initializing from local storage. I'll ignore the key not found case since I've a JQuery version that handles that to prime the storage. Also, the JQuery app reads the ClojureScript saves to localStorage fine. So that's working for me.

Quick summary is this. I message says "There have been $number days since the last incident" The $number is in a div named "counter." I've got three buttons; one increments the count, one decrements the count, and the last resets the count to zero.

 (ns days.core
        (:require [goog.events :as events]
                  [goog.string :as string]
                  [goog.math.Integer :as int]
                  [goog.dom :as dom]))
    (defn initial-state [] 0)
    (def count (atom (initial-state)))
    (defn set-counter [n]
       (do (.setItem (.localStorage (dom/getWindow)) "count" n)
           (dom/setTextContent (dom/getElement "counter") n)))
    (defn set-button-fn [button-id f-update]
       (events/listen (dom/getElement button-id)
                      "click"
                      (fn [] (do (f-update) (set-counter @count)))))
    (defn start-app []
       (do
           (set-counter @count)
           (set-button-fn "addDay" (fn [] (swap! count inc)))
           (set-button-fn "decDay" (fn [] (swap! count dec)))
           (set-button-fn "reset" (fn [] (reset! count 0)))))
    (start-app)

When I try to use goog.math.Integer.fromString() to cast to an integer, the call to inc will append a 1 on the end (7 went to 71 and 711). The call to dec will do what I expect, decrement it numerically (711 went to 710 and 709). Here's how I'm trying to initialize that.

(defn initial-state []
  (integer/fromString (.getItem (.localStorage (dom/getWindow)) "count")))

I realized this was a goog.math.Integer object so I tried to call .toNumber() on it. But this and .toInt() seemed to give me a function. function (){if(this.e==-1)return-w(this).D();else{for(var a=0,b=1,d=0;d=0?e:Ua+e)b;b=Ua}return a}} to be exact.

(defn initial-state [] (.toNumber 
  (integer/fromString (.getItem (.localStorage (dom/getWindow)) "count"))))

Clojure seems to use java's Integer class to cast from a string to an int even to the point of having (int "1") throw so that idea was shot.

I also tried to call javascript's parseInt(). This is how I do it in the JQuery version. However the ClojureScript call always returns a 1. Even if my JQuery version stores an 8 as evidenced by Chrome's developer tools.

(defn initial-state []
  (.parseInt (dom/getWindow)
             (.getItem (.localStorage (dom/getWindow)) "count")))

Any ideas how I can get that string value to behave as an integer? It's got to be simple, but I'm getting nowhere.

3

3 Answers

34
votes

You can access the parseInt function via the js namespace like so:

(js/parseInt "7")
1
votes

Here's a method that works in both Clojure and ClojureScript:

(defn- str->int [s]
  #?(:clj (Integer/parseInt s)
     :cljs (js/parseInt s)))

(str->int "10")
> 10
0
votes

The ClojureScript way:

(ns reader-test.core
    (:require [cljs.reader :as reader]))

(reader/read-string "7") ;; 7 - integer
(reader/read-string "1.3") ;; 1.3 - non-integer number

This works not only for integers, but for any type.