Fork me on GitHub
#beginners
<
2020-02-02
>
jesse00:02:57

Hey! I’m going through http://pedestal.io/guides/your-first-api and I’m at the user=> (require 'main) part but I’m receiving an error of:

Syntax error (FileNotFoundException) compiling at (main.clj:1:1).
Could not locate io/pedastal/http__init.class, io/pedastal/http.clj or io/pedastal/http.cljc on classpath.
I’ve triple-checked and I have my deps.edn and src/main.clj correct. I’ve also just gone through https://tomekw.com/clojure-deps-edn-a-basic-guide/ without any problems, leading me to think that my environment is alright

ghadi00:02:27

check your spelling on that namespace @jesse.claven

ghadi00:02:38

ped`e`stal

ghadi01:02:31

(in the require declaration)

jesse01:02:13

:man-facepalming::skin-tone-3:

jesse01:02:37

I knew it would be something silly, haha. Thank you @ghadi. This is what I get for starting a tutorial at 1am on a Saturday

ghadi01:02:50

it happens :)

jesse01:02:12

to the best of us, I’m sure 😉 haha

piyer03:02:25

Hi Clojurians, I come from javascript/python world. I am trying to understand how the recursion works in clojure. ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5) here is how I would write in javascript: function anon(x) { if (x >0) { return [x].concat(anon(x - 1)); } return []; } In JavaScript, I do write the case for when x === 0, which is my terminating case. Why does clojure return ‘(5 4 3 2 1) and not ’(5 4 3 2 1 nil)?

Nate Sutton03:02:06

because (conj nil 1) returns (1)

Nate Sutton03:02:07

you might want to look at loop and recur

Nate Sutton04:02:46

recursion via calling the current function can be dangerous since clojure doesn't have tail call elimination, meaning you can make the stack level too deep and cause an exception, and loop/recur works around that

em04:02:39

@munichlinux Also consider using the sequence abstractions/library, and try to move away from thinking in terms of loops

(reverse (range 1 6)) ;; sequence functions for working with/iterating over numbers
(take-while pos? (iterate dec 5)) ;; a minimal example of all the logic in your function

piyer05:02:03

@nate_clojurians Thanks, that makes sense. I was trying https://clojurecademy.com/, the example was part of that question.

piyer05:02:33

@eagonmeng

(take-while pos? (iterate dec 5)) 
that looks pretty good. Thanks for that.

hindol10:02:55

Be aware that for very hot loops, loop/recur can be significantly faster as it does not have the overhead of creating sequences. Normally won't matter though.

David Pham11:02:55

Is it possible to decorate all functions in a namespace and redefining them in place? For debugging I would like to log/print the input/output of some function in a defined namespace in a running app. I thought alter-var-root might work but I am unsure.

jumar12:02:50

Cider can do this automatically and I think it just wraps a library.

David Pham15:02:12

Thanks a lot!!

borkdude12:02:10

It can now also be installed using scoop: https://github.com/borkdude/jet#windows

👍 1
❤️ 1
borkdude17:02:24

@software.dev0218 I now also added clojure.edn to the npm package of sci:

> evalString("(require '[clojure.edn :as edn]) (-> \"{:a 1}\" edn/read-string clj->js)")
{ a: 1 }

Polaris21:02:48

Absolutely! 🙂

borkdude11:02:32

(so you now have three ways of converting EDN to JSON: jet, babashka via cli or sci as an npm lib)

pez11:02:43

TIL; There is something called http://exercism.io, and there is a Clojure track: https://exercism.io/my/tracks/clojure

👍 1
hindol13:02:43

Yes, and I can't recommend it enough for beginners.

pez13:02:55

I got stuck on the 17-digit Armstrong numbers test.

pez16:02:26

Cool solution! I just got mentored to find the problem with my solution. Plus some other nice pointers. Such an awesome service. My solution: https://exercism.io/tracks/clojure/exercises/armstrong-numbers/solutions/585ac5a4d0594cd7a2dd36679f8c4494

hindol19:02:48

If I may, Character/digit is a better way of converting char to digit, which I also did not do.

pez19:02:55

You may! Thanks!

Hagenek14:02:10

Hello! I am trying to traverse a vector with map, and convert any string found to a key: This is the function I am trying to use with map:

(defn cs2k
  [v]
  (if (= v str)
    (keyword v)
    v))
This is my vector I am trying it on: [“string” 3 5]

alpox14:02:11

@georghagen I believe you were then looking for (string? v) instead of (= v str)

Cameron14:02:53

yea, (= v str) is asking if v is itself the function str , rather than asking if v is a string

Hagenek14:02:29

Thank you guys! I am still a bit syntax-confused 😃 Guess I should do more koans

andy.fingerhut19:02:01

No problem asking in the #beginners channel about such things, and not trying to discourage you from practice, but str in Clojure is a function you can call, usually to create a string that represents the arguments you pass to it. The expression (= v str) determines "Are the values of v and str equal to each other?", i.e. "Is v equal to the function that is the value of str?"

andy.fingerhut19:02:11

There are a lot of functions in Clojure, and it isn't always clear which one to use when you are new to it. The Clojure cheatsheet might be helpful for you, because it at least tries to divide up the list of Clojure's built-in functions and macros into logically related groups: http://jafingerhut.github.io

👍 1
Hagenek19:02:59

Thank you for a good explanation! It’s only encouraging to get comments like that

Piotr Brzeziński19:02:15

Hey! I’m super new to clojure, and am working through I like it a lot so far, but I’ve a bit stuck and am not sure how to proceed. There’s an exercise that asks me to create a function mapset that takes a function and vector as params and does the same thing that map does but returns a set instead. This is what I tried

(defn mapset
                     [fn v]
                     (loop [remaining v
                            result-set (hash-set)]
                       (if (empty? remaining)
                         result-set
                         (let [[head & tail] remaining]
                           (recur remaining
                                  (into result-set
                                        (set [fn head])))))))
and I feel I’m “almost” there but it doesn’t work. Any help appreciated!

Cameron19:02:43

If I'm reading this right, the first error I see is recurring on remaining each time, instead of tail, since the latter would be the 'rest' of the vector you have yet to have worked on (and remaining refers to your beginning state with the full vector, so if you keep recurring on it, you never are moving forward). The second is [fn head] instead of [(fn head)]

Cameron19:02:58

where the latter will call the function on head, and the former will be adding fn itself into the set

Cameron19:02:27

so the fix would be

(defn mapset 
                      [fn v] 
                      (loop [remaining v 
                             result-set (hash-set)] 
                        (if (empty? remaining) 
                          result-set 
                          (let [[head & tail] remaining] 
                            (recur tail 
                                   (into result-set 
                                         (set [(fn head)])))))))
I believe

Cameron19:02:34

I should check that though to be sure ahaha

Cameron19:02:58

yea so far that works on my side

Piotr Brzeziński19:02:19

So I was almost there lol

Piotr Brzeziński19:02:30

Stupid mistake, thanks @zdot101!

Piotr Brzeziński19:02:44

Just to confirm that I understand it right. The recur tail only runs within the let [[head & tail]… block? Or does it re-run whole mapset?

ghadi19:02:03

neither, recur goes to the nearest loop header

👍 1
ghadi19:02:39

an fns are implicit loop headers

👍 1
Piotr Brzeziński19:02:43

That makes sense. Thank you.

Cameron19:02:57

other small things: I may be missing something, but I don't think you need to call (hash-set) , and can instead use the first class syntax for sets (ie, writing #{} in its place). Also, instead of (into result-set (set [(fn head)])), you should be able to just call (conj result-set (fn head)) , where the latter is flat out just saying "add (fn head) to set" and the former is saying something like "create a vector containing just (fn head) , then immediately turn it back into a set, and conjoin these two sets"

Piotr Brzeziński19:02:46

Awesome, good feedback, thank you very much.

Piotr Brzeziński19:02:02

I still find lisp’s syntax a bit confusing 😛