Fork me on GitHub
#beginners
<
2018-03-09
>
mfikes01:03:51

In the Apropos podcast, the 2nd half has live video where we work through small problems at the REPL, with this being geared towards exploring things in a way that might be helpful to beginners. If interested, here's the link https://youtu.be/WyISHu0JFpg

pooboy02:03:04

Failed to deploy artifacts: Could not transfer artifact clorandom:clorandom:jar:1.0.0. from/to releases (): Failed to transfer file: . Return code is: 400, ReasonPhrase: Bad Request.

pooboy02:03:27

Guys I'm getting this error..when i do lein deploy

gonewest81803:03:48

The extra “.” at the end of 1.0.0. looks suspicious to me.

noisesmith03:03:34

it's weird, but it also shouldn't matter

pooboy03:03:30

Stack overflow suggested to add -SNAPSHOT to the last 0

noisesmith03:03:49

SNAPSHOT has a specific meaning

noisesmith03:03:40

it wouldn't hurt to add itif that's what you mean (that it is meant to be repeatedly re-released), but it isn't needed

noisesmith03:03:25

@suryapjr if an artifact version ends in -SNAPSHOT leiningen / maven / boot etc. will look for a new version before running and use it if available

noisesmith03:03:37

(a new version of that snapshot version that is)

pooboy03:03:42

Ohhhhhh...cool

pooboy03:03:49

Without snapshot ?

pooboy03:03:19

Kindly check my project.clj

pooboy03:03:44

(defproject clorandom "1.0.0-SNAPSHOT"
  :description "A simple wrapper around the Java Random class"
  :url "     "                                             :license {:name "Eclipse Public License"                   :url ""}                                       :dependencies [[org.clojure/clojure "1.8.0"]]  
  :deploy-repositories [["releases"  {:sign-releases false :url ""}]                                ["snapshots" {:sign-releases false :url ""}]]) 

noisesmith03:03:31

yes, that looks like it should be fine

pooboy03:03:03

My username and password are correct

pooboy03:03:36

After adding -SNAPSHOT,it deployed

noisesmith03:03:47

so I guess it didn't like the version ending in .

pooboy03:03:04

Thank you !

pooboy03:03:58

How can I add additional functionality to it in the future

noisesmith03:03:18

you can change your code and deploy again, with snaphsots that's allowed

noisesmith03:03:35

for non-snapshot releases, you need to change the version so it is unique

pooboy03:03:32

Ohhhh..cool

pooboy03:03:39

So with spanshot

pooboy03:03:03

Clojure will automatically do it 1.1.0

noisesmith03:03:08

no, the version stays 1.0.0-SNAPSHOT or whatever, but lein will pick the newer one

pooboy03:03:51

So now i have added my module as a dependency in my project.. So now i should call my function directly ?

pooboy03:03:45

Or it should (namespace/myfunction)

noisesmith03:03:17

use require to make sure the namespace is in scope, use :as in require to give it a shorter alias

pooboy03:03:45

great !! Thanks !

pooboy05:03:36

Hi guys !!

pooboy05:03:12

Thank you all for your support at each step !!❤️

pooboy06:03:55

(ns name.core
    (:gen-class))
 
 (defn -main[] (
 
  println "Hi whats your name")
   (def name (read-line))

 (println( str("Hi " name))

  (println "Where are you from ")
  (def place (read-line))
  (println "You are ",name, "from", place)

)

pooboy06:03:07

Guys im getting EOF error at line 4

hawari06:03:36

Seems like you have unmatched parentheses there @suryapjr

pooboy06:03:34

Yessss yess

hawari06:03:14

No problem, may I suggest you to take a look at this as well? Readability comes a long way if you don't opt to use tools for matching parentheses https://github.com/bbatsov/clojure-style-guide

pooboy06:03:22

yes !! Ill go through it !

pooboy06:03:37

Clojure rocks Man !

seancorfield06:03:17

@suryapjr Don't put def inside functions!

pooboy07:03:06

Does clojure has mutable lists ?

hawari07:03:25

No, it doesn't

pooboy08:03:30

And what is an Atom

pooboy08:03:26

Having a bit of trouble.. understanding atom

hawari08:03:32

Atom refers to an "identity", unlike the traditional "variable" concept, Clojure has very different idea regarding values.

hawari08:03:27

I suggest that you learn Clojure gradually from the ground up @suryapjr. IMHO it's more rewarding than by simply "converting" what you already have learned from another language. Sometimes, it's even necessary to unlearn some. This book has been very helpful for me through my earlier phase of learning Clojure: https://www.braveclojure.com/clojure-for-the-brave-and-true/

pooboy08:03:46

@hawari.rahman17.. I'm learning it from living clojure

pooboy08:03:52

From the basics

hawari08:03:58

Forgive me for assuming. I have that book as well, but from skimming it just before, It seems that the earlier chapters from the book lack the depth required for a newcomer to Clojure. It jumps straight on how to write a functioning Clojure code instead of slowly introducing on why things are the way they are on Clojure.

gklijs09:03:08

I really liked clojure for the brave and true as well, read it on vacation without a laptop, so didn’t do the exercises, but gave a good overview of the syntax and general idea.

nakiya10:03:16

I have this code in a cljs file:

(doseq [ra (reverse received-ats)]
                             (-> @chart .-data .-labels (.push ra)))
                           (doseq [ts (reverse temps)]
                             (-> @chart .-data .-datasets (aget 0) .-data (.push ts)))
 
chart is created as (def chart (atom nil)). It then stores a chart.js chart. Couple of questions about the above code: 1. If I use for instead of doseq, their bodies do not execute. Why? 2. received-ats and temps have same number of elements. How can I combine these two loops into a single one?

pooboy10:03:29

@gklijs Clojure for the brave and true is an excellent read

noisesmith10:03:40

@duminda for is not a loop, it's a lazy list comprehension, it does nothing until something consumes the data it is generating

noisesmith10:03:59

in that code, there's nothing interesting returned by those bodies, so there's no reason to use for

noisesmith10:03:02

doseq is literally the same as for except not lazy (and allowing multiple forms in its body)

orestis11:03:27

@duminda map accepts multiple collections — so you could something like:

user=> (doseq [[x y] (map list [1 2 3] [1 2 3])] 
         (prn (* x y)))
1
4
9
nil

;; where
user=> (map list [1 2 3] [1 2 3])
((1 1) (2 2) (3 3))
(taken from clojuredocs https://clojuredocs.org/clojure.core/doseq#example-542692c6c026201cdc32691b)

noisesmith11:03:47

@orestis @duminda doing that only makes sense if your operation requires both values, and you know both inputs are the same length, and I don't think either applies in the code pasted

orestis11:03:07

Isn’t that what point 2. says? Or did I misread?

noisesmith11:03:48

I totally missed that - I still think it's clearer as two loops since the ops are unrelated

noisesmith11:03:28

and I bet the extra lists being created are more expensive than looping twice if it's a perf concern

orestis11:03:08

If I understand the context is chart data — where you have one list with x values, one list with y values, and you somehow need to munge them together.

magra13:03:03

A macro created a local id from a keyword :db/id. I have the keyword and want to access the local. (name :db/id) returns id, but as a string. How do I access the local named "id" with the string "id". Or is there a more direct way from the namespaced keyword to the local?

schmee13:03:11

do you want to access it inside the macro or outside?

magra13:03:24

I just want to turn the string into a symbol I guess.

magra13:03:59

I am inside a defsc (fulcro).

schmee13:03:46

try (resolve (symbol s)), where s is your string

magra13:03:55

That returns

Assert failed: Argument to resolve must be a quoted symbol
(core/and (seq? quoted-sym) (= (quote quote) (first quoted-sym)))

magra13:03:02

hmm. it seems to work in clj but not in cljs.

magra13:03:02

hmm. maybe resolve is not what I am looking for. (symbol (name :db/id)) seems to give me the symbol. How do I get from there to the content of the local the symbol points to?

magra13:03:53

How do I "deref" it?

Russ Olsen13:03:23

@magra If you have the symbol then either resolve or ns-resolve will give you the var, which is sort of a value container. var-get will get you the value.

Russ Olsen13:03:02

(var-get (resolve (symbol "x"))) will get you the value of x.

Russ Olsen13:03:12

But, this only works for symbols that are def'ed. Bindings created via let are kind of in a different world.

schmee13:03:36

try using (resolve &env (symbol s)) instead

magra13:03:40

Thank you @russ767. That works in the clj repl. But cljs does not get past the resolve statement. And yes, I would need that for locals, not def'd symbols. Am I thinking about this wrong? Is there a more sensible way to go from a keyword to the content of a local by the same name?

magra13:03:28

Have I maybe reached the point where I need to learn to write macros?

Russ Olsen13:03:01

So I would hesitate to say "you are doing it wrong" (people do that way too often) but I'm not sure I've ever had the problem you are describing. A macro may be the solution. What are you trying to do at a higher level?

avfonarev13:03:17

I know the question must have been asked 100 times, but once again. What book/sequence of books would you recommend to learn clojure? Background: I have no problem with functional programming, understand the syntax, and am able to do, say, all of the advent of code. However, there are things I’m extremely uncomfortable with in clojure: concurrency, records vs. plain maps, handling state in a small, but non-toy application, basically, anything “real world”.

schmee13:03:08

The Joy of Clojure sounds like a good fit for you! It’s the one Clojure book I refer back to again and again. It goes into great depth about everything in the core language, including all reference types like atoms. But it doesn’t cover “systems”-level state management like Component, Integrant etc.

sundarj13:03:38

Programming Clojure too 🙂

Russ Olsen13:03:42

You might try Clojure Applied as well.

timo13:03:39

Anyone ever built a polling trigger kind of thing with a re-frame event? I need to poll an api every 500ms. How do you create an event for such kind of things?

magra13:03:49

The whole thing is in a defsc macro that returns a react component.

magra13:03:19

The resolving of the symbol part is after the :defaultValue keys.

Russ Olsen13:03:50

@magra So my knowledge of cljs is pretty limited, but the words "write that code for me" suggest a macro to me.

magra13:03:46

I was afraid of that 😉 Thank you @russ767 and @schmee!!

nakiya14:03:25

@timok : perhaps you can have a look at the first example in the re-frame tutorial here: https://github.com/Day8/re-frame/blob/master/docs/CodeWalkthrough.md Basically fire an event from a timer.

alexk14:03:49

Depending what the latency is like, how many clients there are, and how client-specific the API call is, I’d consider writing the poll loop on serverside, and streaming down to the client(s)

Russ Olsen15:03:22

@magra My advice to beginning macro writers is to start by writing an ordinary function that takes takes the arguments you think you will pass to the macro (keeping in mind that macro args don't get evaluated, so ' is your friend here) and outputs the code that you think the macro should output. Once you have that working, switch from defn to defmacro and see what happens. This way you can start out in the ordinary world of garden variety functions and work from there. You can do the reverse as well - turn your misbehaving macro into a regular function to debug it. And of course there is macroexpand.

magra16:03:01

The nasty bit is that the expanded stuff needs to contain a syntax-quoted expression. So the nesting of the quotes and unquotes is confusing.

magra16:03:57

Or maybe it doesn't.

Russ Olsen16:03:01

Just keep repeating this to yourself: Syntax quoting is just like HTML templating where instead of {{foo}} or <%= foo %> or whatever you have ~foo.

magra16:03:04

Thats a really good tip!

jonathan17:03:41

Hello, I'm reading the third edition of Programming Clojure. In the chapter on Clojure.spec it defines an example spec for clojure.set/intersection. When the spec is tested using s/conform the vector is quoted. But all other examples thus far are using a regular (unquoted vector).

We can spec the arguments to intersection as follows.
(s/def ::intersection-args
(s/cat :s1 set?
:sets (s/* set?)))
(s/conform ::intersection-args '[#{1 2} #{2 3} #{2 5}])
-> {:s1 #{1 2}, :sets [#{3 2} #{2 5}]}

jonathan17:03:26

Is there a reason why this specific example uses the quoted vector '[#{1 2} #{2 3} #{2 5}] ?

jonathan17:03:38

In my REPL it returns the same result whether it's quoted or not

sundarj17:03:34

no reason that i can see - you typically only need to quote stuff when lists/symbols are involved. i wouldn't worry about it 🙂

jonathan17:03:50

ah ok thanks. The next example refactors it but still uses a quoted vector so I thought there's some special case with sets.

sundarj17:03:16

probably just an oversight

mbjarland17:03:29

I'll ask this in beginners as that is how I feel with this issue. Over the past month or so my lein repl invocations have intermittently started hanging and finally bailing out with a REPL server launch timed out.. If I start the server with :headless in one invocation and connect to it with :connect it works. This breaks even outside of projects running lein in an empty directory. clj has no issues starting a repl. lein -v -> Leiningen 2.8.1 on Java 1.8.0_161 Java HotSpot(TM) 64-Bit Server VM

mbjarland17:03:51

Reboot is the only thing I've found "fixes" this and then only for a while

mbjarland17:03:27

top of the main thread jstack output for the hanging lein repl invocation:

"main" #1 prio=5 os_prio=0 tid=0x00007f0aa800b800 nid=0x3e49 waiting on condition [0x00007f0aaf02b000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x0000000719974700> (a java.util.concurrent.FutureTask)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426)
	at java.util.concurrent.FutureTask.get(FutureTask.java:204)
	at clojure.core$future_call$reify__6962.get(core.clj:6699)
	at clojure.tools.nrepl.ack$wait_for_ack.invokeStatic(ack.clj:32)
	at clojure.tools.nrepl.ack$wait_for_ack.invoke(ack.clj:16)
	at leiningen.repl$server.invokeStatic(repl.clj:250)
	at leiningen.repl$server.invoke(repl.clj:232)
	at leiningen.repl$repl.invokeStatic(repl.clj:320)

mbjarland17:03:07

ok -finally- figured out the cause of this. Seems I have a vpn solution which is a tad greedy and somehow prevents the repl from starting. Seems strange to me as the repl is starting on 127.0.0.1...but after disconnecting it started working.

jar2317:03:27

any ideas why would a program run 3x faster when I add a simple call to print?

noisesmith17:03:32

you were realizing a lazy seq that was returned, and the print means you don't realize that lazy seq any more?

noisesmith17:03:08

eg. if a function looked like (defn foo [] ... (for ....)) and it changed to (defn foo [] ... (for ...) (println ...)) - now the for doesn't run

jar2318:03:25

maybe, but no lazy anything in this particular program AFAIK. all that’s being printed is a string fetched from a hashtable.

jar2318:03:19

effectively (let [name (get …)] ?(print (format "%s\n" name)) other-stuff)

noisesmith18:03:19

so the print isn't changing what's returned somewhere?

noisesmith18:03:49

then there's some other confounding variable

jar2318:03:15

well that’s what I would think, but for the life of me I can’t figure out what it is

noisesmith18:03:32

you can look at criterium if you want to get accurate microbenchmarks https://github.com/hugoduncan/criterium

noisesmith18:03:59

3x is inside the band of noise for naiive benchmarking with (time ...)

jar2318:03:14

I’ve just been trying to do just that, and it baffles me… it seems to want to run the code 50 times, which is prohibitive. Playing with overriding the defaults now

noisesmith18:03:31

you can't get an accurate benchmark with a single run

jar2318:03:39

I don’t want an accurate benchmark.

noisesmith18:03:41

you can use quick-bench for less accuracy and less runs

jar2318:03:14

I just want a vague idea why runtime goes from 30 seconds to 120 seconds by making what should be a totally inconsequetial change

jar2318:03:37

I tried quick-bench and it still wants me to wait a long time… I lose patience after 5 minutes or so

noisesmith18:03:56

that's not answerable with the amount of information you provide, other than saying measurements are unreliable using time

jar2318:03:25

repeatable, always about 4x difference, that seems reliable to me.

jar2318:03:41

I know I haven’t given much info, it’s too big & preliminary too post

noisesmith18:03:47

OK then no answer can be given with the amount of info you provide

jar2318:03:51

just looking for ideas on how to approach

jar2318:03:15

thought maybe someone had encountered something like this, or knew docs to read, etc.

noisesmith18:03:58

another option is to do proper profiling, for example using visualvm or yourkit

Elena18:03:56

I'm spec'ing. How should I go about doing this collection of collections of ints and other collections? ([0 (0 2)] [1 (1 4)]

Elena18:03:33

I want to check that each vector has an int? and a s/coll-of int?

jar2318:03:59

@noisesmith thanks for listening

noisesmith18:03:49

sorry I couldn't offer something more concrete - I have a strong hunch once you find it it will be something very simple

manutter5118:03:14

@jar23 I wonder if you could narrow it down by selectively replacing top-level functions with stubs that return dummy data. Kind of a binary search, find the top-level fn that makes your program run faster when you replace it, then drill down and replace the functions inside that

jonathan18:03:06

@elena.caraba I'm just reading the a chapter on clojure.spec so I gave it a shot but I have no idea if this is idiomatic

jonathan18:03:14

(s/conform (s/+ (s/tuple int? (s/coll-of int?))) [[0 '(0 2)] [1 '(1 4)]])

jonathan18:03:00

Ensure it fails for non integers:

(s/explain (s/+ (s/tuple int? (s/coll-of int?))) [[0 '(1.2 2)] [1 '(1 4)]])
In: [0 1 0] val: 1.2 fails at: [1] predicate: int?

jonathan18:03:10

If you want to allow for an empty collection you can change s/+ to s/*

Elena18:03:14

@jonjanisch Interesting thought about using tuples. I'm thinking if every or every-kv may be what I want/need.

jonathan18:03:11

I believe those are for large collections where you don't want to test all (just some subset)

jonathan18:03:34

But I'm a complete beginner and have never spec'ed anything 😄

Elena18:03:27

Thanks for trying to help, though!

jonathan18:03:25

I think you can simply change s/+ to s/every also:

(s/explain (s/every (s/tuple int? (s/coll-of int?))) [[0 '(1.3 2)] [1 '(1 4)]])
In: [0 1 0] val: 1.3 fails at: [1] predicate: int?

jonathan18:03:30

And you can change s/tuple to s/cat if you want to tag them for better error messages:

(s/explain (s/every (s/cat :my-int int? :my-int-coll (s/coll-of int?))) [[0 '(1.3 2)] [1 '(1 4)]])
In: [0 1 0] val: 1.3 fails at: [:my-int-coll] predicate: int?

Kara23:03:22

Is there some succinct clojurescript way to write the equivalent of return a || b; in other words use a if it is true (not empty in my case) otherwise use b?

eggsyntax00:03:09

Minor clarification based on "use a if it is true (not empty in my case)": Note that in clojure/script, empty sequences are truthy. You can use seq or empty? on them if you want to detect non-emptiness.

user> (if () :truthy :falsey)
:truthy
user> (if (seq ()) :truthy :falsey)
:falsey

bsima23:03:21

i think (or a b) works @kara

bsima23:03:54

but test that at a repl, because it depends on what a actually is

Kara23:03:17

ah, thanks I was looking everywhere for that or operator... I just completely missed it -_-;;;

bsima23:03:44

@kara another function you might want to use is https://clojuredocs.org/clojure.core/some_q