'clojure returning hello world and nothing in the output

I just started learning Clojure and I have my own Clojure script but it's not returning the output that I am hoping for (Hello World). Here is my code:

(ns com.playground.core
  (:gen-class))

(defn -main 
  [] 
  ((defn CHEESE
     []
     (str "Hello World"))

   (CHEESE)))

This is the output that I get in the REPL:

clj꞉com.playground.core꞉> 
#'com.playground.core/-main

I want to see Hello World in the output.



Solution 1:[1]

You have a double parentheses there. Try this:

(defn -main
  []
  (defn CHEESE
    []
    (str "Hello World"))
  (CHEESE))

Of course your MUST call -main, otherwise you'll see nothing:

(defn -main
  []
  (defn CHEESE
    []
    (str "Hello World"))
  (CHEESE))
=> #'com.playground.core/-main
(-main)
=> "Hello World"

I see your define a function inside another function. You should use let or letfn for this purpose.

Solution 2:[2]

Starting a REPL for the project does not run -main. Running your program produces the following:

Execution error (ArityException) at com.playground.core/-main (core.clj:6).
Wrong number of args (1) passed to: com.playground.core/-main/CHEESE--177

What is happening?

  1. The defn form creates and registers a function under the name CHEESE in the com.playground.core namespace.
  2. The defn form returns the created var, which evaluates to the function.
  3. The containing ((defn ...) (CHEESE)) form applies the CHEESE function to (CHEESE), the result of evaluating the CHEESE function without arguments,
  4. ... which is the string "Hello World".

It doesn't matter what the argument is, because CHEESE has no arity 1 invocation: you can't apply it to any argument.

You can get the same (bad) effect more simply by pulling the defn for CHEESE out of -main. While we're at it, let's drop the str, which has no effect:

(defn CHEESE []
  "Hello World")

(defn -main []
  (CHEESE (CHEESE)))

Execution error (ArityException) at com.playground.core/-main (core.clj:8).
Wrong number of args (1) passed to: com.playground.core/CHEESE

To put it right, we simply drop the (CHEESE)argument:

(defn -main []
  (CHEESE))

producing ...

Process finished with exit code 0

No returned value, but at least it ran. But if we evaluate (-main) in a REPL, ...

(-main)
=> "Hello World"

There.

Solution 3:[3]

Actually, It's not exactly wrong. This return is the "return of declaration".

For example, you defined a -main in the com.playground.core namespace.

The return is the symbol of this declaration #'com.playground.core/-main

To print the Hello world message you need to call the function CHEESE after the declaration.

enter image description here

So... about double parenthesis, it's not good, but not impact hehe. Another point is the function name, it's not good too. Consider using kebab-case.

You also consider keeping the function declaration more explicitly. Something like that;

(ns com.playground.core
  (:gen-class))

(defn CHEESE [] (str "Hello World"))

(defn -main []
  (CHEESE))

But also did it you're not printing the Hello world. Your only declaring a function (CHEESE) that returns a String type.

To print, you need to call a print function.

(ns com.playground.core
  (:gen-class))

(defn hello [] (str "Hello World"))

(defn -main []
  (print (hello)))

I did the evolution of declarations to explain better

enter image description here

So, you can improve the code using the let alternative and the threading macros

Consider use the https://kimh.github.io/clojure-by-example/ and https://tryclojure.org/ to understand these options better :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Thumbnail
Solution 3