Search code examples
clojurestdinclojurescriptclojure.specnrepl

Clojurescript first steps doubts and problems


I just started with clojurescript and I have many doubts, what I want to do is use clojurescript only to solve basic problems, for now nothing to do with web.

If I eliminate the web development part, would there be any difference between coding in Clojure and ClojureScript? or is it exactly the same?

Also I was wondering if I can use the command cat DATA.lst | clj program.cljs to run clojurescript code? Or is the compiler different? If so, how can I compile clojurescript code

Regarding the official page, it presents a very limited hello world !, the following line is delivered by the page as a command to compile clojurescript.

clj --main cljs.main --compile hello-world.core --repl

  1. It only prints something if I use the --repl command, if I delete this, the console stops printing the result, the problem is that, things it prints is very different, to if on the other hand, it compiled the code using the command for clojure cat DATA.lst | clj program.cljs

  2. It is totally web-oriented so all the time it is opening in my browser and showing something related to that topic, which would have nothing to do with my case.

  3. I would like to know how I can execute my code so that I am sure that I am compiled for clojurescript and not for clojure (in case they were different)

  4. It is necessary to create the complex project tree that exposes the page or I can leave it in a folder in a simple way. (This is how I work with clojure)?

  5. The code I'm trying to compile is the one below, it's simple, I just read stdin and process the info as I want it to be at the end

(defn get-data []
  (let [input-string (read-line)]
    (lazy-seq
      (if (seq input-string)
          (cons (clojure.string/split input-string #" ") (get-data))
          nil))))

(defn get-mod [data]
  (lazy-seq
    (if (seq data)
        (cons (map (fn [x] (rem (Integer. x) 12)) (first data))
          (get-mod (rest data)))
        nil)))

(defn main []
  (def data (rest (get-data)))
  (def module (get-mod data))
  (println module))

What vscode gives me in the terminal when I use the line of code that gives the official clojure script page is the following:

WARNING: When invoking clojure.main, use -
ClojureScript 1.10.758
cljs.user=> 33
cljs.user=> 50
57
54
69
cljs.user=> 72
80
68
56
63
cljs.user=> 47
71
40
56
59
52
cljs.user=> 74
59
78
66
cljs.user=> 74
62
94
82
77
cljs.user=> 50
66
57
54
cljs.user=> 68
72
63
44
56
cljs.user=> 60
48
79
75
63
cljs.user=> 67
51
58
cljs.user=> 66
78
51
60
54
cljs.user=> 56
52
49
25
61
cljs.user=> 36
53
45
48
cljs.user=> 58
61
42
49
54
cljs.user=> 76
80
68
68
60
cljs.user=> 63
58
54
51
58
cljs.user=> 42
50
54
54
58
cljs.user=> 50
59
54
62
66
54
cljs.user=> 65
41
61
49
56
cljs.user=> 27
48
43
55
cljs.user=> 35
43
35
47
28
cljs.user=> 49
44
52
32
44
cljs.user=> 74
58
65
70
53
cljs.user=> 52
56
40
60
52
cljs.user=> 54
69
69
62
cljs.user=> 52
49
56
76
cljs.user=> 58
66
50
70
50
cljs.user=> 82
70
73
77
70
cljs.user=> 56
51
63
35
cljs.user=> 59
67
52
71
79
cljs.user=> 72
72
76
84
57
cljs.user=> 66
61
58
61
cljs.user=> 49
32
52
32
cljs.user=> 64
33
52
64
49

Which is exactly the same information that I enter in stdin, that is, it did nothing of what my code dictates, what it should deliver is the following:

((2 9 6 9) (0 8 8 8 3) (11 11 4 8 11 4) (2 11 6 6) (2 2 10 10 5) (2 6 9 6) (8 0 3 8 8) (0 0 7 3 3) (7 3 10) (6 6 3 0 6) (8 4 1 1 1) (0 5 9 0) (10 1 6 1 6) (4 8 8 8 0) (3 10 6 3 10) (6 2 6 6 10) (2 11 6 2 6 6) (5 5 1 1 8) (3 0 7 7) (11 7 11 11 4) (1 8 4 8 8) (2 10 5 10 5) (4 8 4 0 4) (6 9 9 2) (4 1 8 4) (10 6 2 10 2) (10 10 1 5 10) (8 3 3 11) (11 7 4 11 7) (0 0 4 0 9) (6 1 10 1) (1 8 4 8) (4 9 4 4 1))

Solution

  • Clojure is a language that runs on the Java Virtual Machine. ClojureScript is a similar language in appearance and features, but it is compiled to JavaScript and will run on JavaScript runtimes such as NodeJS or the JS engines in web browsers. Because they target different runtimes, there are differences, explained here: https://www.clojurescript.org/about/differences

    Some functions like readline are not available in ClojureScript and you'll need to write your own using JS interop, creating your own event handler. You can write code for Node that blocks and waits for input using something like the core.async library but it's way beyond beginner level.

    Your code actually looks like it would work in Clojure so, unless you have some reason to stick to Node and avoid the JVM, I'd stick to plain Clojure to learn the language with all the resources that are available.

    Here's a simple example project and program that sums the numbers that are entered from the standard input:

    The project has this structure:

    .
    ├── data.txt
    └── src
        └── demo
            └── core.clj
    

    The main program:

    (ns demo.core)
    
    (defn -main [& args]
      (loop [total 0]                  ;; initialize a total sum to 0
        (if-let [line (read-line)]     ;; keep any input as `line`, otherwise else branch
          (let [n (read-string line)]  ;; parse `line` to number
            (recur (+ n total)))       ;; loop, 'updating' the total
          (println total))))           ;; else branch: no input, print the total so far
    

    The data file data.txt:

    11
    22
    33
    

    ... and finally an example run:

     cat data.txt | clj -m demo.core
    WARNING: When invoking clojure.main, use -M
    66