Fork me on GitHub
#beginners
<
2018-12-19
>
Jin Choi00:12:58

Hello πŸ™‚

Jin Choi00:12:50

A question for you guys. I got confused with a word phrase while I was reading a official Clojure document for transient at https://clojure.org/reference/transients#_how_they_work What does that mean by bashed in-place as in the following quote: > Note in particular that transients are not designed to be bashed in-place. You must capture and use the return value in the next call. FYI, I think I got the most feel of this feature, transient. Just to make sure if I've missed something.

andy.fingerhut00:12:33

It means basically that you should always use the return value of operations like conj! disj! assoc! etc., just like you would if it were the non-! version of that function, rather than using the original transient collection that you passed to conj! disj! assoc! etc., when making further modifications.

andy.fingerhut00:12:26

There is a little bit more discussion of that in the http://ClojureDocs.org examples for assoc! here: http://clojuredocs.org/clojure.core/assoc!

andy.fingerhut00:12:06

Ask more questions if that doesn't help make it clear. That page is very quickly and easily editable for anyone, so quick to improve it if you know what wording might be confusing there.

andy.fingerhut00:12:25

Actually, one thing that I may have been unclear about above: the phrase "just like you would if it were the non-! version of that function".

andy.fingerhut00:12:19

When we are talking about regular persistent collections, not transients, you can take a collection named m and do something like (conj m 5). After that returns, both m and (conj m 5) are still persistent collections, on which you can do the full set of persistent operations on.

andy.fingerhut00:12:06

When you take a transient-ified collection m and do (conj! m 5), you should pretend like m is undefined, and never refer to it again. It may or may not be the identical object as returned from (conj! m 5).

Jin Choi01:12:04

@andy.fingerhut Thanks to you , I learned what it's supposed to mean. However, the phrase be bashed, is it a, some kind of lingo for CS? I tried to reason the contextual meaning by referring to English-English dictionary (say, https://dictionary.cambridge.org/dictionary/english/bash) but meanings seem mostly for hit or criticize. The best guess for the word be bashed under the circumstances, in my opinion, is be bashed == be modified. Please correct me if I am still confused.

manutter5101:12:33

That is correct: be bashed is being used in the sense of be modified. It’s a metaphorical usage, meant to be more fun to read than a more literal be modified would have been.

Jin Choi01:12:41

@manutter51 Yeah. Now, I can feel a dynamic action in the phrase, if I got it right. Thanks alot !!

manutter5101:12:38

Yup, you got it.

πŸ’― 4
seancorfield01:12:22

I think it stems from ! being called "bash" in some tech circles...

seancorfield01:12:03

(I'm used to it being called "bang" but I think I've seen "bash" used occasionally)

jaawerth04:12:32

excuse me but the technical term is "bonk"

jaawerth04:12:39

(no it isn't, I just couldn't help myself)

4
seancorfield01:12:41

Imagine taking a mallet and changing the transient value in place by bashing it repeatedly with the mallet πŸ™‚

πŸ‘ 8
Jin Choi02:12:48

In the given sense, we could also name assoc! and conj! as bashing functions because they are bang functions and bang and bash are inter-changible in some tech circles. Haha

jstaab01:12:20

it's a good metaphor

jstaab01:12:50

attaches a little bit of stigma to mutability as is good and proper

Ali Ebadian09:12:43

Hey all again, I am following this https://clojurebridgelondon.github.io/workshop/functions/name-smash.html on this site, this works: (def students ["Ada Lovelace" "Anne-Marie Imafidon"]) (clojure.string/split students #" ")

Ali Ebadian09:12:02

However in my repel I get an exception

Ali Ebadian09:12:19

ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.CharSequence clojure.string/split (string.clj:219)

Ali Ebadian09:12:26

I am sure its me thats at fault here, i just dont know what ive done

rivas09:12:40

I think you may need to map it over the collection?

danielneal09:12:47

Yes, In your code above, students is a vector ["Ada Lovelace" "Anne-Marie"]

rivas09:12:57

If you want to split each name by space, I mean

danielneal09:12:08

clojure.string/split needs a string as input

danielneal09:12:42

so you need to call split on each student, as opposed to the vector of students

rivas09:12:49

(map #(clojure.string/split %1 #" ") students) would work

Ali Ebadian09:12:49

So in the little online repel on this site the output is:

Ali Ebadian09:12:50

["[\"Ada" "Lovelace\"" "\"Ali" "Ebadian\"]"]

Ali Ebadian09:12:15

then the site goes into map and flatten to make it look nicer

rivas09:12:02

I don't understand why that works there!

danielneal09:12:32

I think it's because this is clojurescript, which is hosted on javascript

πŸ‘ 8
danielneal09:12:41

the vector is being turned into a string implicitly, I guess because that's what javascript does

danielneal09:12:55

This is why the [ are included in part of your output

danielneal09:12:10

(def students ["Ada Lovelace" "Anne-Marie Imafidon"])
(clojure.string/split (str students) #" ")

danielneal09:12:14

It's having ^ this effect

Ali Ebadian09:12:37

also the site doesnt really explain whats the rol of #

danielneal09:12:16

that # is put infront of a string to make a regular expression pattern

danielneal09:12:47

so you can do e.g. #"[a-z0-9]+" and that kind of thing

rivas09:12:15

#() : function, #"": regex

schmee09:12:50

more generally, it’s a reader macro: https://clojure.org/guides/weird_characters#dispatch

πŸ‘ 4
Ali Ebadian09:12:10

that makes more sense.

Ali Ebadian09:12:17

Sorry about all these questions btw, it looks like i only learn by trying and breaking things then questiong what went wrong (good thing I am not a doctor)

danielneal09:12:42

don't worry, this is a great way to learn a language, no-one gets hurt πŸ™‚

Ali Ebadian09:12:05

While you guys are being far too kind, i am going to show my utter nobiness by the next question

Ali Ebadian09:12:22

i see a lot of reference to lazy sequences in the docs

Ali Ebadian09:12:52

but no real good explaintion on what are sequences or lazyness

rivas09:12:00

A sequence is just a collection of things: so eg '(1 2 5 "hello" "cool")

joelsanchez09:12:10

you will see # used for literal sets too #{1 2 3}

πŸ‘ 4
joelsanchez09:12:21

and vars #'my-var

rivas09:12:31

and a lazy sequence is a ruleset for generating a sequence

rivas09:12:02

so if you call, for example, (range 1000000000000000), it won't actually generate a range of 1 squillion numbers straight away

rivas09:12:07

that's why it's lazy

rivas09:12:46

But if you do (take 100 (range 100000000000000)), you'll get the numbers 1 to 100 in a sequence

rivas09:12:12

If you're familiar with generators from python, I think they're the same thing

Ali Ebadian10:12:28

so if I want the last number in that range, it will generate everything and get the last number?

Ali Ebadian10:12:13

or does it do something clever and it workout

schmee10:12:30

nothing clever, it has to generate the whole sequence

rivas10:12:32

I think it has to run to the end, yes

schmee10:12:54

however, if you only want the last number, it doesn’t keep all the intermediate stuff in memory

Ali Ebadian10:12:57

so from earlier code (map #(clojure.string/split %1 #" ") students) returns a lazy squence of ("Ada" "Lovelace" "Anne-Marie" "Imafidon")

rivas10:12:20

No, it should return a normal sequence of (("Ada" "Lovelace") ("Anne-Marie" "Imafidon"))

rivas10:12:01

then flatten will turn the sequence of sequences into a single sequence

Ali Ebadian10:12:31

` user=> (type (map #(clojure.string/split %1 #" ") students)) clojure.lang.LazySeq `

rivas10:12:45

then yes, I guess it's lazy

Ali Ebadian10:12:08

Again sorry about these silly questions

rivas10:12:10

I should note I came here to ask a question before getting distracted, I'm very much also A Beginner

Ali Ebadian10:12:34

i guess there is levels to beginners

Ali Ebadian10:12:06

I am white in my introductory class, you're graduating from your white belt class

Ali Ebadian10:12:14

I am not sure if anyone will find this useful, but it just blew my mind

rivas10:12:07

That is very interesting, Ali, I had some trouble working out the difference myself

rivas10:12:29

Anyway, my question: is there an easy way to split a sequence into equally-sized sequences? It seems like something I'd find in the standard library but couldn't...

rivas10:12:05

I wrote this function, but I doubt it's the best way:

(defn split-on-width
  [values width]
  (loop [remaining values
         new       []]
    (if (empty? remaining)
      new
      (let [[head tail] (split-at width remaining)
            next-new    (concat new [head])]
        (recur tail
               next-new)))))

rivas10:12:21

ah, yep, I knew it'd be there

rivas10:12:24

Thanks pavlos!

πŸ‘ 4
rivas10:12:07

That is very interesting, Ali, I had some trouble working out the difference myself

Daouda12:12:18

Hey folks, apply is not about taking each args and apply on a function? Why this doesn't work (apply inc [1 2 3])

bronsa12:12:34

no, that's map

bronsa12:12:45

apply is about turning a list of arguments into arguments to a function

bronsa12:12:53

e.g. (apply + [1 2 3]) => (+ 1 2 3)

bronsa12:12:25

(map inc [1 2 3]) =~> (list (inc 1) (inc 2) (inc 3)) (modulo laziness)

Daouda12:12:21

when should i use apply?

Daouda12:12:59

here`(apply + [1 2 3])` i am seeing (apply func coll)

Daouda12:12:07

(apply inc [1 2 3]) is also (apply func coll) so what i am getting wrong?

bronsa12:12:28

look at the example above

bronsa12:12:48

(apply func [el1 el2 .. eln]) does (func el1 el2 .. eln)

bronsa12:12:59

it splices the elements in coll as arguments to func

bronsa12:12:33

it doesn't apply func to each element in coll

bronsa12:12:35

that's map

Daouda12:12:46

so (apply inc [1 2 3]) should not apply inc to each element also?

Daouda12:12:05

ooooooooooow

Daouda12:12:11

i think i got you know

Daouda12:12:39

it will just take each element of the coll and pass them as argument to to inc but inc accept only one arg at time

Daouda12:12:44

i am right?

bronsa12:12:56

what you're doing is (inc 1 2 3)

bronsa12:12:00

which makes no sense

Daouda12:12:26

hehehehehe, got it now

Daouda12:12:39

thank you very much for your patience

anonfish13:12:59

What does the args definition mean here?

(s/defn render-pulse-section :- RenderedPulseCard
  [timezone {card :card {:keys [data] :as result} :result}]

anonfish13:12:19

I don't understand this part: {card :card {:keys [data] :as result} :result}

madstap13:12:08

It's a nested destructuring, there's a guide on the official site https://clojure.org/guides/destructuring

anonfish13:12:33

So, making keys in the underlying available in the top-level map?

anonfish13:12:55

which is the top-level object and which one is nested?

bronsa13:12:38

the input map will look like {:card a :result {:data b ..}}

bronsa13:12:09

you'll get card bound to a, data bound to b and result bound to {:data b ..}

madstap13:12:20

These should be equivalent:

(defn foo [{card :card {:keys [data] :as result} :result}]
  ,,,)

(defn foo [m]
  (let [card (:card m)
        result (:result m)
        data (:data result)]
    ,,,))

hoopes15:12:48

Hi, in development for a http-kit server application using mount, I'm using lein repl and doing (mount/start), which starts my server listening (within the repl process, i'm guessing?). My core.main function is very simple:

(defn -main [& args]    
  (mount/start))
However, when i do lein run, it exits immediately - this seems like a really silly question, but how do I keep the process up and running here?

hoopes15:12:03

(exits immediately after starting all the mount components, I should say - the code is working fine, i just need the server to stay up and listening)

sova-soars-the-sora16:12:47

@hoopes what's the bottom of your project.clj look like? that is where you can define specific lein commands

hoopes16:12:29

26   :profiles {:dev {:source-paths  ["dev"]
 27                    :repl-options {:init-ns user}
 28                    :dependencies [[org.clojure/tools.namespace "0.2.10"]
 29                                   [org.clojure/java.classpath "0.3.0"]]}
 30                                                                   
 31              :uberjar {:main ws.core
 32                        :aot :all}}
 33                                                        
 34   :aliases {"dev" ["with-profile" "+dev" "repl"]
 35             ;"make" ["clean" "uberjar"]
 36             }
 37   )

hoopes16:12:04

https://github.com/tolitius/mount/blob/uberjar/test/app/app.clj#L16 reading this...now i'm just wondering what i'm doing wrong πŸ™‚ my example looks just like that

hoopes16:12:07

i think my mount components were just broken, and not throwing the error properly

mitch18:12:09

does anyone have experience working with the chestnut template?

mss19:12:47

hey all, is there an idiomatic way to pull out the first value from a collection that satisfies a predicate? like some, but returning the actual value that matches instead of true. would prefer to avoid filtering through the rest of a large-ish collection with an expensive op if I can avoid it

yuhan20:12:53

btw, filter returns a lazy sequence so doing (first (filter pred coll)) should give the same result without consuming more of the collection than it needs

jumar07:12:24

chunked seqs may have an impact here, though.

schmee19:12:38

you can do something like (some #(when (your-pred %) %) coll)

mss19:12:17

some returns a true or nil if no match, no? looking to return the actual match

schmee19:12:56

it returns the first truthy value, which in this case will be %, ie the match

jstaab19:12:34

@mss the predicate provides the return value rather than some

dpsutton19:12:46

> Returns the first logical true value of (pred x) and here pred returns nil or x

mss19:12:59

ohhh I misread the docs and was repl-ing around in a way that made me misunderstand

mss19:12:03

thanks for the help y’all

πŸŽ‰ 4
dylandrake19:12:07

when using hiccup to generate html, if I want to include jQuery via the google CDN, do you have to use the with-base-url util? like so:

(util/with-base-url "https:" (page/html5 (page/include-js            
     "//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js")))
because I cannot get it to work

byrongibby19:12:35

Hi. I am wondering if someone could help point me in the right direction. I need to instantiate a Java interface using new as well as overriding a method of the interface. I led myself to believe I could do these two things in two steps using reify to instantiate the interface and then pass it to another class' method, but then the method of the said class doesn't seem to recognise the "reified" interface's type. I might be way off the mark with all of this as I am not an experienced coder, and have no real knowledge of Java, but I don't seem to be making any more progress on Stack Overflow.

byrongibby19:12:50

This is the code I am trying to translate to clojure directly:

myButton.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                // display pin state on console
                System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
            }

        });

byrongibby19:12:59

This is my attempt in Clojure:

(def listener (reify GpioPinListenerDigital
                (^void handleGpioPinDigitalStateChangeEvent [this ^GpioPinDigitalStateChangeEvent event]
                 (println (str " --> GPIO PIN STATE CHANGE: "
                               (.getPin event) " = " (.getState event))))))

(.addListener myButton listener)

Chris19:12:01

What error do you get?

byrongibby04:12:39

Hi @UA8TV3QHF, thanks for the reply. Below is the error message:

IllegalArgumentException No matching method found: addListener for class com.pi4j.io.gpio.impl.GpioPinImpl  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79)
I amtrying to do a naive translation from http://pi4j.com/example/listener.html

Chris17:12:34

Cool, glad you got it πŸ™‚

jstaab21:12:51

Hey there, is there any way to use core.logic or core.unify to write an algebra solver, particularly when working with arbitrary sequences? Something I could say a = b + (sum cs) - (sum ds), give it a, cs, and ds and get a out?

jstaab21:12:59

Also being able to distinguish between applying sequences of multipliers in parallel (`10 + 10% + 10% = 120`) vs in serial (`10 + 10% + 10% = 121`) would be helpful

andy.fingerhut21:12:28

There most likely is, but I suspect it wouldn't be a small amount of code, even given the help you would get from relying on core.logic and core.unify. There are commercial systems like Mathematica and open source alternatives (Octave? Maxima? I haven't checked recently to see what is current there) that might be worth examining, unless one of your primary goals is keeping it in Clojure

jstaab21:12:37

I've been using wolfram alpha to help me through the stickier bits, so I imagine Mathematica is close to what I want. However, it's really just for a small amount of tricky domain logic, maybe ~400 lines worth. I'm just looking for a way to avoid implementing the equation in both directions basically.

andy.fingerhut21:12:49

This StackOverflow topic may have some leads, but I haven't read through the linked topics to see what their quality might be: https://stackoverflow.com/questions/12592118/how-to-solve-math-equations-using-core-logic

jstaab21:12:55

I saw that, don't think it'll do for my use case. https://github.com/clojure-numerics/expresso looks interesting though

andy.fingerhut21:12:59

This Google groups discussion is from 2012, but some of the people involved may have done some work that would interest you: https://groups.google.com/forum/#!topic/clojure/fRuTGeW5Wm4

andy.fingerhut21:12:44

espresso looks more current than anything I have found yet.

jstaab21:12:32

Cool, thanks for the links

nikola21:12:56

Is anyone using Atom as a Clojure editor? Do you have autocompletion working?

jaide22:12:41

If I got a clojure symbol like 'java.lang.IllegalArgumentException how can I resolve that to its actual class?

jaide22:12:44

facepalm That works. I tried that but for some reason I thought it was just returning a symbol. πŸ˜”

jimbob23:12:39

cani get test code in an uberjar? ex: i have tests under test directory i want to run during a smoke test of production but not sure its in the uberjar it doesnt seem like it is

seancorfield23:12:34

@ben.borders None of the tools I know of will put tests in an uberjar. What you could do is put those particular tests under the src directory somewhere and perhaps add a -main function that will run those tests (so you can easily run the tests in production).

πŸ‘ 4
jimbob23:12:11

yep that makes sense. kind of where im headed as well at this point

seancorfield23:12:25

But I would be very wary of running tests in production -- just in case anything destructive gets into those tests.

πŸ‘ 4
jimbob23:12:34

now the question is how not to have main early exit, since test running is printing results