Fork me on GitHub
#beginners
<
2018-09-16
>
Sal06:09:15

Is it possible to run a one file clojure program with a main function just using clj command?

Bobbi Towers07:09:01

As outlined here https://clojure.org/guides/deps_and_cli you run it with $ clj -m hello

Sal07:09:06

@porkostomus Thank you sir. I had tried that before and it was not working. After looking at the link you provided, I realized I need to have my file inside a directory named src

henrik08:09:06

@fuentesjr If you’re looking to make a script, you can also use #planck or #lumo.

👍 4
Denis G08:09:31

how to you iterate through seq using when, first and rest I've seen an example before. Can not find it again You still need loop, right?

Denis G09:09:00

(loop [s (seq s)]
    (when (seq s)
        (do-smth (first s))
        (recur (rest s))

Denis G09:09:05

smth like this?

henrik09:09:36

@denisgrebennicov It depends. In most cases you can just map, reduce, transduce or the numerous variations thereof. A minimal example of looping would be,

(loop [item (first items)
       items (rest items)]
  (when item 
    (recur 
      (first items)
      (rest items))))

henrik09:09:38

Usually you want to return something, in which case when needs to be if

(loop [item (first items)
       items (rest items)]
  (if-not item
    "Done!"
    (recur 
      (first items)
      (rest items))))

henrik09:09:17

And if you want to accumulate results, you need to put an additional clause in the loop,

(loop [item (first items)
       items (rest items)
       collector []]
  (if-not item
    collector
    (recur 
      (first items)
      (rest items)
      (conj collector item))))

Denis G09:09:38

Perfect, thanks!

👍 4
Denis G09:09:21

've been doing simple brackets matcher right now. Any ideas of how could I make the solution more "clojury"?

(def open-brackets #{\{ \[ \(})
(def close-brackets #{\} \] \)})

(defn not-nil? [x] (not (nil? x)))

(defn opposite? [a b]
    (case [a b]
        ([\) \(] [\] \[] [\} \{]) true
        false))

; Complete the isBalanced function below.
(defn isBalanced [s]
    (loop [s (seq s) stack '()]
        (if (seq s)
            (cond 
                (not-nil? (open-brackets (first s)))
                (recur (rest s) (cons (first s) stack))
                
                (not-nil? (close-brackets (first s)))
                (if (opposite? (first s) (first stack))
                    (recur (rest s) (rest stack))
                    "NO"))
            (if (= 0 (count stack))
                "YES"
                "NO"))))

henrik09:09:23

To begin with, check out some?, the opposite of nil?: https://clojuredocs.org/clojure.core/some_q

Denis G09:09:09

@henrik the some API is so crazy. There is some and some?. Can not get used to it 😅

Denis G09:09:11

some should be any or smth 😄 But any is already reserved AFAIK. But of course you are right. Fair point

henrik10:09:32

Also, if you’re only interested in some characters, you can filter with the set of interesting characters, so you don’t have to deal with anything else in your conditionals.

Denis G10:09:36

In this case the input was guaranteed to be of a specific type. Of only valid input chars (brackets) But always a good thing to think about

henrik10:09:51

Oh, right. Is not-nil only to deal with brackets that you might not have in the set then?

Denis G10:09:57

Exactly. The bracket is either in one set or another. Wanted to use case, but case tests for true/false AFAIK. Therefore, thought it wouldn't work

henrik10:09:09

I think the loop could be converted to a reduce that builds a seq of opening characters when it finds them, and removes them in order when encountering a closing character. reduced can be used to abort reduce when a closing character not matching the last opening character is found. Wrap it in empty?, and that will give true or false for if it’s balanced or not (since empty is balanced).

henrik10:09:45

I don’t think reduce would offer much of an improvement in performance, but it might be interesting just to see how it works.

Denis G10:09:27

Isn't loop more readable? Breaking from reduce feels smhow wrong, dunno :thinking_face:

Denis G12:09:47

@U09FPJ924 still, not convinced that breaking from reduce is a good idea. Just conceptually it doesn't make sense. Like stopping, while mapping. Huh?

rmprescott12:09:34

Think of it as having converged to your solution. Aside: for this problem, I don't think you have to, either. Look at my 4clojure solution to P177.

Denis G13:09:08

@U09FPJ924 this is more a philosophical question, rather than related to my problem. It just doesn't feel right to break while doing map/filter/reduce, operations which originally planned to be done on whole collection. It doesn't imply that my gut feeling is right.

rmprescott14:09:54

😁 mathematics vs computation

😅 4
henrik10:09:59

It totally depends on what you’re used to reading, and how well you document 🙂

Denis G10:09:21

does Haskell, ML or any other language allow you to break from reduce?

henrik10:09:49

I’m not sure, but I’m pretty sure it’s a valid thing to do. Sometimes you’re reducing over an infinite (or very, very large) sequence to satisfy some condition.

henrik10:09:50

But loop is totally valid of course. I tend to go for transducers when I can, because they’re higher level constructs, and I figure that in most cases my implementation is going to be worse than theirs.

Denis G10:09:35

This is a matter of preference I guess, I think that if your reducer accumulator is like an array of 5 elems, then it feels somehow wrong, isn't it? Maybe just not used to it

sb10:09:57

What is the best data transfer between clojure and clojurescript? I saw rest slow, sente via websocket. I use now websockets. Could I use other solution?

sb10:09:11

I created a macro based db between parts and works fine without ws, rest. Is that normal or can kill things? Somebody created something similar or tried?

henrik10:09:10

Unless you need to expose the API for outside consumption, sending EDN via a single endpoint, whatever it may be, could be a sufficient solution.

henrik10:09:19

I’ve found websockets to a bit finicky to work with with regards to reconnecting and so on, but from what I know, Sente is pretty good at handling that.

sb13:09:33

For me the API was slow, ws works but not fine as you wrote. Now i solved with direct connection with cljs macro call. I can write clj db and read, just i dont know is here side-effect or not. Btw much faster than ws, as I see

sb13:09:41

In short, I try to solve the one db thing in this case.

sb13:09:38

I drop to github and smarter people will comment it. What they think about..

sb10:09:30

(I didn’t test fully now)

henrik10:09:04

@denisgrebennicov Here’s my (hamfisted) attempt at a reducer equivalent. For brackets not in the set I’m checking for, I just break the evaluation and say “unbalanced”, since I’m unable to verify it either way. I guess throwing might be more proper.

henrik10:09:24

Note that I did a boo-boo and used the reserved word char as a parameter name 😕

Denis G10:09:02

@henrik thanks. Interesting solution 😉 The thing is opening closing brackets as hashmap key value pairs is smart 🙂

henrik10:09:00

Thank you! Yeah, opening brackets is automatically keys, and closing is automatically vals. Though they don’t come out as sets.

Denis G10:09:37

But this can be easily done by using set function

henrik10:09:00

The let is almost entirely unnecessary, but I find that let helps me break stuff down into smaller pieces when solving a problem.

henrik10:09:39

Sometimes I go back and remove them if they’re too silly.

Denis G10:09:54

it makes things more readable. I love readable namings. Coming from Obj-C it's common sense 🙂

👍 4
henrik10:09:29

Actually, I found a corner-case in the above solution. With multiple closing brackets, it would return true when the stack was empty. To avoid that, I put the offending closing bracket onto the stack before calling reduced.

👍 4
sb16:09:55

I have a question: (clojure.core/swap! (symbol "atom") conj 2) I got: ClassCastException java.lang.String cannot be cast to clojure.lang.IAtom clojure.core/swap! How can I create IAtom from string without deref like (eval (list deref (symbol “atom”)))?

sb16:09:49

Sorry, I solved.

sb16:09:26

I just want to give to a macro a string which create a swap command

sb16:09:35

exactly the atom name

borkdude16:09:51

@sb any reason you’re not giving a symbol to the macro instead of a string?

sb16:09:40

isnt work.. (swap! string …) do you need to add (swap! (from string symbol) .. or not?

sb16:09:08

one moment

sb16:09:19

true.. 🙂

sb16:09:45

@borkdude oops, thanks 🙂

rmprescott18:09:41

any common idiom/macro to map truthy to an explicit true or false ?

rmprescott18:09:15

I usually don't bother but this problem requires it.

noisesmith18:09:18

boolean does this

rmprescott12:09:31

You'd think I would have recognized this pattern by now. :face_palm:

noisesmith16:09:02

it's rarely needed - everything in clojure proper is fine with truthey / falsey

rmprescott00:09:47

I meant the pattern of "type as-a function". I.e.

((juxt short int double float boolean) 1 )
=> [1 1 1.0 1.0 true]
(map class *1)
=> (java.lang.Short java.lang.Integer java.lang.Double java.lang.Float java.lang.Boolean)