Fork me on GitHub
#beginners
<
2021-03-04
>
Adrian Imanuel05:03:25

hi, there's much efficient method than this, but I'm stuck with this. any advice? the code is 1. creating a sequence of prime numbers 2. then pairs it 3. then calculate the gap/difference between pairs 4. if the condition met with the pairs' difference it'll return the 1st list of the pairs

(defn is-prime? [n]
  (and (< 1 n)
       (not (some #(= 0 (mod n %)) (range 2 n)))))

(defn prime-seq [from to]
  (filter is-prime? (range from (inc to))))


(defn gap [g m n]
  (first (remove nil?
                  (for [i (vec (partition 2 1 (prime-seq m n)))]
                    (if (= g (- (second i) (first i)))
                      i)))))

V06:03:55

What exactly is the desired output you are looking for?

V06:03:02

If the pair (3 5) meets the condition, you only want to return 3 or a list of the first elements of all pairs that meet the condition?

Adrian Imanuel06:03:07

could the gap function can be optimized more? to give quicker time processed? the code I wrote, is already running okay, but i look for more efficient method

Adrian Imanuel06:03:05

the result is to : return list of the first elements of all pairs that meet the condition

delaguardo09:03:43

(defn gap [g m n]
  (let [primes (prime-seq m n)]
    (for [[m' n'] (map vector primes (next primes))
          :when (= g (- n' m'))]
      m')))
this is not an optimization, but a slight refactoring of the gap function

Adrian Imanuel08:03:42

Hi, i got an error with this function

Syntax error (IllegalArgumentException) compiling recur at (*cider-repl 3. Clojure\Practice Learning:localhost:51246(clj)*:59:13).
Mismatched argument count to recur, expected: 2 args, got: 1
What i want to do is like this
(defn searchings
  [y somevec]
  (when (< y (count somevec))
    (if (not (nil? (get somevec y)))
      (get somevec y)
      (recur (inc y)))))
so i can do something like this (searchings 0 [nil nil '(3 5) nil]) and return (3 5) , how to modify the function?

V08:03:36

You need to recur with both arguments, currently you only provide y in your recursive call. You need to include somevec as well

V08:03:04

(defn searchings
  [y somevec]
  (when (< y (count somevec))
    (if (not (nil? (get somevec y)))
      (get somevec y)
      (recur (inc y) somevec))))

3
dharrigan09:03:31

also, the idomatic way is to do (if-not ,,,)

dharrigan09:03:20

additionally, get will return nil if nothing found, so you could shorten it further

dharrigan09:03:55

i.e., (if (get somevec y) ,,,)

Adrian Imanuel11:03:06

@U01GQRC8W30: oooo okay noted. @U11EL3P9U if-not noted.. I'll try... Thanks a lot!

pavlosmelissinos12:03:39

(if (get somevec y))
  (get somevec y)
  (recur (inc y) somevec))
can further be shortened to: (or (get somevec y) (recur (inc y) somevec))

11:03:51

I'm starting to read How to Design Programs and wanted to know how different is Scheme and Clojure. Can I use clojure to follow the book?

raspasov12:03:56

Not a Scheme expert, but I think quite different. Even though general good software principles are transferable from language to language, you might have a hard time following unless you know both languages quite well. If you really want to read the book, I would stick with Scheme for the time being. If you want to do Clojure, there’s probably better books out there to teach good Clojure program design.

raspasov12:03:42

Perhaps this comment by Rich Hickey is relevant to this discussion https://groups.google.com/g/clojure/c/jyOuJFukpmE/m/aZjWHBnsQ74J

Adrian Imanuel12:03:37

Hi everyone, I've tried to solve this, and the code works fine, but it said execution time out 12000 ms which I should revise & made it more efficient. https://www.codewars.com/kata/561e9c843a2ef5a40c0000a4/train/clojure here's my code, any idea how to make this more efficient? I'm kinda stuck here.

(defn is-prime? [n]
  (and (< 1 n)
       (not (some #(= 0 (mod n %)) (range 2 n)))))

(defn prime-seq [from to]
  (doall (filter is-prime? (range from (inc to)))))


(defn gap [g m n]
  (first (remove nil?
        (for [i (vec (partition 2 1 (prime-seq m n)))]
          (if (= g (- (second i) (first i)))
            i)))))

delaguardo12:03:07

just remove doall from prime-seq function

Adrian Imanuel12:03:27

i've tried that, same result, still time out

delaguardo12:03:02

also algorithm is not really eficient I can recommend to read that article - https://www.thesoftwaresimpleton.com/blog/2015/02/07/primes

Adrian Imanuel12:03:24

allrite will read that, and try it on... thank you for sharing

Stuart14:03:50

Your isprime is VERY slow. For a start you are checking its not a multiple of all the numbers from 2 to n, you only need to check up to the square root of n. You could also do a check if the number is even and if it is you can exit out early with false.

Stuart14:03:35

Maybe faster to generate all the primes under the limit for n, stick them in a set and check against that set when you need to?

Fernando de Paula Carvalho14:03:57

Hello. I have a list of maps. Between these maps can have duplicate keys. And I need to "concat" the values of the maps with duplicated keys. List example: (def a '({"a" {"x" "xxx"}} {"b" {"y" "yyy"}} {"a" {"z" "zzz"}})) I need to transform it into: '({"a" {"x" "xxx" "z" "zzz"}} {"b" {"y" "yyy"}}) I'm trying to use "map" with "merge-with" to make it, but it generates a list-result with the same duplicated "a" key. Anyone can help-me?

tvirolai14:03:13

(apply merge-with into a) should do it

💯 3
Fernando de Paula Carvalho14:03:23

Thanks, solved my problem!!

andarp16:03:58

What’s a good way to use Clojure for scripting? What type of setup? My easiest way to start using the language in the real world is to make small file processing scripts. Right now I’m writing them in Cursive using a regular old project and running them with the repl but once I’m done I would like to use them as command line scripts I could eg pipe file content to etc. How do I go about that?

Eamonn Sullivan16:03:37

I've been writing command-line utilities for the last year or so at work -- dev-op kinda things. Lately, I'm a convert to babashka, but sometimes you're doing something a bit more complicated and it isn't yet supported in babashka, like using an internal, private lib or something. I do the following: • Generate an uberjar • Write a shell script that you can put on a path somewhere. It should basically just run java -jar <your-uberjar>.jar $@ (the last $@ thing just passes on the args). We have a Homebrew repo at work that automates this for colleagues. They just have to run brew install <my-awesome-cli> and the above steps are done for them. And they don't need to know they were written in Clojure...

Eamonn Sullivan16:03:42

I haven't yet done this yet, but presumably I should be able to write many of these in babashka now and just make bb a dependency in my Homebrew formulas.

andarp16:03:47

Will bb support packages from the “official” channels?

Eamonn Sullivan16:03:15

I'm barely conversant on babashka still, but on your next CLI, I would just try and see how far you get. For me, running the jar files was working well enough that I hadn't even glanced in babashka's direction. Plus my CLIs are somewhat chunky, so I still think that was the correct approach. For example, I wrote a CLI to query our hundreds of microservices to find those using a particular runtime environment or dependency. That involved combined several different APIs (internal and external) and the tooling for a full-blown Clojure JVM app is just better for that. But if I'm trying to do something that could almost be accomplished with a bash script, but where the script would get into dozens of lines, then I'll use babashka. Best bet: ask in #babashka about your particular use cases.

telekid18:03:51

I’d estimate that a 500 line babashka CLI app is saving my team 1h per person per week, and I’ve put less then ~5 hours into the script in the last year. It’s a serious game changer.

dharrigan16:03:06

wouldn't babashka help?

borkdude16:03:32

babashka is designed for this use case

grazfather16:03:19

#babashka for sure

Hagenek16:03:25

Hi you lovely people. Does ayoone know: How do I add this library https://docs.datomic.com/on-prem/javadoc/datomic/Util.html to my classpath using Leiningen? I am basically going to use it to read edn-data from a file and turn it into a clojure data structure

dpsutton16:03:02

is you goal to read a local edn file and turn it into Clojure datastructures?

Hagenek16:03:27

Yes exactly

dpsutton16:03:45

yup. that's where i was going to point you

🎉 3
Hagenek16:03:18

Let’s see if I can get it to work with IO now 😃

raspasov16:03:14

(clojure.edn/read-string (slurp "deps.edn"))

dpsutton16:03:39

lots of examples here too: https://grep.app/search?q=edn/read. You can browse to see how people use io/reader in addition to the handy read-string

dpsutton16:03:14

is my go-to to find examples. How does a pushbackreader get constructed, etc

Hagenek16:03:18

Will check it out — Down the rabbit hole I go!

dharrigan17:03:41

Be sure to come up for air now and again

Seb19:03:15

Hello! Just started learning about Clojure this past week. Quick question for anyone: I’m looking to find an example/project tutorial that walks through building an app that has a clojure backend and a clojurescript frontend

seancorfield19:03:04

If you're just getting started, you might want to start with a small, purely Clojure web app using just the Ring and Compojure libraries before you also try to learn about ClojureScript tooling -- it is a bit overwhelming for some beginners, depending on their background.

seancorfield19:03:43

There are no beginner-friendly frameworks in Clojure/Script like there are with many other languages. What are you familiar with @seb.wildwood?

Seb19:03:19

With regards to programming in general, I’ve got years of experience in Python/JS/Go and newish experience with Elixir

Seb19:03:41

What’s the best, minimal Clojure stack for a simple REST API that you’d recommend @seancorfield?

seancorfield20:03:06

I recommend starting with Ring (for the web server abstraction) and Compojure (for routing), and then look at Hiccup (generating HTML from Clojure data) and/or Selmer (Django-style templating).

seancorfield20:03:23

I often point beginners to this example project https://github.com/seancorfield/usermanager-example but the readme also links to an implementation that uses Reitit for routing (and Integrant instead of Component for managing the start/stop lifecycle of pieces of the app).

seancorfield20:03:21

It's not intended as a step-by-step tutorial, but it is meant to be a well-commented example of what a small, server-side rendered, database-backed Clojure web app might look like.

🙏 3
seancorfield20:03:56

I don't know what state this online book/tutorial is right now, but it might be a good place to look when you want to start exploring ClojureScript https://practicalli.github.io/clojurescript/ (be aware that the cljs world has a lot of options for how you build stuff). This will probably be helpful for (server-side) Clojure web apps: https://practicalli.github.io/clojure-webapps/

seancorfield20:03:00

For REST, rather than HTML responses, you could look at compojure-api which builds on top of Compojure to focus on REST API features.

seancorfield20:03:19

@jr0cket is usually very responsive if you have questions about his online books/tutorials (and he has a great deps.edn file to learn from, for the Clojure CLI). There's also a #practicalli channel to dive deeper into his material.

👍 6
Seb20:03:58

Thanks for the guidance! Much appreciated

Jim Strieter21:03:09

Hey, I'm a noob. I'm trying to instantiate a class from a local Java jar. The jar is a package which contains more layers of packages, then of course classes.

Jim Strieter21:03:38

I already added the path to the local jar in :resource-paths in project.clj

Jim Strieter21:03:09

lein repl starts with no error, so I take that to mean the import statement is correct

Jim Strieter21:03:47

When it comes to instantiate a class from the jar, that's where existing posts (from other forums) don't seem to be relevant

noisesmith21:03:54

what import? adding to path is not importing and isn't an error if the path specified doesn't exist

Jim Strieter21:03:05

I'm getting there

noisesmith21:03:22

instantiating a class is just a question of using it, import is only a convenience so you don't have to type out the full name

noisesmith21:03:31

classes are loaded when referenced

Jim Strieter21:03:54

one class in the jar is called AccountValue

Jim Strieter21:03:04

So in at the repl, I expect to be able to type:

noisesmith21:03:13

are you trying to create an object of that class, or use a static method?

Jim Strieter21:03:19

create an object

noisesmith21:03:53

I didn't meant to interrupt, please do share what you tried and what the error was

Jim Strieter21:03:30

Since the repl seems to know the names of things in the namespace, I figure I ought to be able to type 'A', tab

Jim Strieter21:03:39

and then the repl will offer AccountValue as one of the options

Jim Strieter21:03:42

But that is not happening

noisesmith21:03:48

a repl won't do that

noisesmith21:03:57

because you haven't done anything that loads the class

Jim Strieter21:03:05

ok how do i load the class

noisesmith21:03:38

(foo.bar.AccountValue. arg1 arg2 ...) (replace foo.bar with the real package, and figure out the args you need to the constructor)

noisesmith21:03:59

or use (import foo.bar.AccountValue) then (AccountValue. ...)

noisesmith21:03:45

you'd need the import before the "A" autocompletes

Jim Strieter21:03:04

Thank you man 🙂

Jonathan Dannel21:03:22

hey guys, can anyone tell me how i can deal with a response after a POST request with the clj-http package? i honestly can't find anything after googling

ghadi22:03:04

what did you try @usixjad?

ghadi22:03:37

post what you evaluated, and what it evaluated to?

Jonathan Dannel22:03:01

(defn translate [body]
  (let [lang (body "language")
        text (body "text")
        resp (client/post watson
                          {:content-type :json
                           :body "{\"text\":[\"Hello, how are you today?\"],\"model_id\":\"en-es\"}"})]
    resp))

(defroutes app-routes
  (POST "/translate" {body :body}
    (response (translate body))))

Jonathan Dannel22:03:05

just getting the 500 stacktrace

ghadi22:03:24

post that

ghadi22:03:28

in a snippet, please

ghadi22:03:34

CMD-shift-enter

Jonathan Dannel22:03:07

the 500 is just the default ring/compojure 500

Jonathan Dannel22:03:49

get requests work fine, and sending back some dummy data to postman in json is fine, but i'm not sure if client/post takes a callback or anything

hiredman22:03:07

a 500 sounds like an error on the server side

hiredman22:03:19

are you logging stacktraces?

hiredman22:03:02

the 500 error that clj-http throws will likely include the stacktrace in the :body

ghadi22:03:22

posting the error will show whether the 500 is from your route doing something wrong, or a 500 from the endpoint that your route calls

hiredman22:03:27

alternatively put a try/catch around your call to translate and print any exceptions

hiredman22:03:38

very likely translate is throwing an error because whatever body is isn't callable as a function

ghadi22:03:41

another good thing to practice is separating the process of gathering input to a process (here an external call) and making the call itself consider making translate only return the argument to client/post

ghadi22:03:55

then you can inspect that at the REPL to ensure it's legit

ghadi22:03:04

then... make the call

ghadi22:03:01

but back to the errors, they're not some annoyance from Java, they contain useful context

ghadi22:03:07

I am not (yet) sure from your description that you are drawing the right conclusion https://clojurians.slack.com/archives/C053AK3F9/p1614895507209200

Jonathan Dannel22:03:21

ah, give me a moment

Jonathan Dannel22:03:59

okay, sorry about that. i was using my API key wrong, and i've gotten it to work with postman; you're right -- the request was failing because i wasn't authenticated

Jonathan Dannel22:03:05

(defn translate []
  (let [resp
        (client/post watson
                     {:content-type :json
                      :basic-auth ["apikey" apikey]
                      :body "{\"text\":[\"Hello, how are you today?\"],\"model_id\":\"en-es\"}"})]
    (response resp)))

(defroutes app-routes
  (POST "/translate" {body :body}
    (translate)))

Jonathan Dannel22:03:26

i've modified my code so that i'm not actually taking any request params or anything now, just sending a simple string to the API

Jonathan Dannel22:03:37

my question still stands with how to get the response back. here's the stacktrace

ghadi22:03:49

it's important to structure your code so that you can bang on stuff while you write working dough vs. setting into motion a large Rube Goldberg machine by dropping a marble

Jonathan Dannel22:03:10

yep 😛 very new to clojure still so..

ghadi22:03:41

what is the main error you see?

Jonathan Dannel22:03:46

in the stacktrace, it's clear that i'm binding the actual http client object to a variable

ghadi22:03:15

call (translate), then inspect your result

ghadi22:03:21

break the problem down

ghadi22:03:16

com.fasterxml.jackson.core.JsonGenerationException
Cannot JSON encode object of class: class org.apache.http.impl.client.InternalHttpClient: org.apache.http.impl.client.InternalHttpClient@2e20c4f7

ghadi22:03:38

that's the main cause listed in the trace

ghadi22:03:11

the JSON generator appears to be trying to serialize the HTTP Client itself into the payload

ghadi22:03:37

I should be clearer: call (translate) from within your REPL

Jonathan Dannel22:03:44

(defn translate []
  (let [resp
        (client/post watson
                     {:content-type :json
                      :basic-auth ["apikey" apikey]
                      :body "{\"text\":[\"Hello, how are you today?\"],\"model_id\":\"en-es\"}"})]
    (get resp :body)))

(defroutes app-routes
  (POST "/translate" []
    (response {:result (translate)}))
  (route/not-found "<h1>Page not found</h1>"))
  

Jonathan Dannel22:03:32

the response map being nil was the problem, i guess

ghadi23:03:42

great, but don't guess!

Jonathan Dannel23:03:41

yeah, still trying to figure out exactly why..

ghadi23:03:58

translate used to return the whole response from clj-http -- but now you're picking out a particular piece of it (`:body`)

Jonathan Dannel23:03:34

and sending the actual hash map for it to be valid json

ghadi23:03:36

I haven't looked at clj-http in a while, but there must have been some additional stuff being returned that the JSON serializer didn't know how to handle

ghadi23:03:08

vs {:result whole-response-from-clj-http}

Jonathan Dannel23:03:27

ahh, i see what i was doing incorrectly

Jonathan Dannel23:03:41

is this generally the way to deal with responses from post requests?

ghadi23:03:02

maybe? depends on the http library being used

ghadi23:03:12

this is generally the way I debug any issue though

Jonathan Dannel23:03:28

i'm so used to promises in javascript.. will execution halt until there is a success/failure?

ghadi23:03:36

break it down, evaluate in my editor, put it back together

ghadi23:03:46

correct, this library happens to be synchronous

ghadi23:03:26

there are options to provide a callback, or you can run it in a future, or use a different lib

Jonathan Dannel23:03:07

i asked the question initially because i honestly couldn't find anything saying that client/post may accept a callback

Jonathan Dannel23:03:17

guess i didn't look hard enough

ghadi23:03:28

yeah clj-http is one of the oldest libs out there, it's accrued piecemeal design over time

Jonathan Dannel23:03:15

i usually pride myself in my debugging, but learning clojure is kind of throwing me for a loop tbh

Jonathan Dannel23:03:21

guess i'll take it slower

ghadi23:03:59

when I started with Clojure, it took me about 6 months to "get it"

ghadi23:03:12

I was pretty new to programming at the time, and I had to unlearn all the OOisms

ghadi23:03:31

but yeah, working with the REPL like you're working dough

Jonathan Dannel23:03:19

speaking of that, i actually wasn't able to get into my repl

ghadi23:03:33

it's super fun, much more productive than set up magic entry point that prearranges the world -> compile -> wait -> pray

ghadi23:03:14

so this is something i'm noticing with a lot of Clojure developers, even experienced ones

ghadi23:03:20

...not using the REPL

ghadi23:03:35

doing something like lein test every time you save a file, etc.

Jonathan Dannel23:03:51

so, i run lein repl and immediately get pages of errors

Jonathan Dannel23:03:02

and i don't actually know how to load the namespace

ghadi23:03:07

post em in a snippet

ghadi23:03:11

don't give up 🙂

ghadi23:03:23

which editor are you using?

ghadi23:03:53

you really don't want to use the terminal REPL (but still shouldn't have any stacktrace from it)

dpsutton23:03:00

and there's a general truism, don't make loading namespaces do work. makes it close to impossible to not be able to get into a repl or require namespaces. this can often be why things break before you can get at them

dpsutton23:03:11

you probably have an old cider/cider-nrepl in your ~/.lein/profiles.clj

ghadi23:03:18

I gotta run -- but there are hundreds of people here that can continue helping -- happy trails!

Jonathan Dannel23:03:27

thanks so much @ghadi, really appreciate it 😄

Jonathan Dannel23:03:42

@dpsutton i'll check my profiles file

dpsutton23:03:04

or somehow you're getting cider related stuff into the project

Jonathan Dannel23:03:38

this is my profiles.clj

Jonathan Dannel23:03:42

{:user {:dependencies [[nrepl "0.8.3"]
                       [cljfmt "0.5.1"]]
        :plugins [[cider/cider-nrepl "0.25.5"]
                  [lein-cljfmt "0.7.0"]]}}

Jonathan Dannel23:03:32

not sure why i have both nrepl and cider-nrepl

Jonathan Dannel23:03:39

i think i might have added it for vim functionality

Jonathan Dannel23:03:23

removing the cider plugin seems to have solved that

dpsutton23:03:50

excellent. if you need those back, there was an issue with that version of cider-nrepl. replacing it with "0.25.9" should fix it

theequalizer7323:03:51

hi, how can I turn this seq (\0 \0 \1 \1 \4 \0 \1 \7 \8 \0 \0 \1 \6) into a number 11401780016 ?

noisesmith23:03:11

shortest path is probably (->> your-input (apply str) (Long/parseLong))

noisesmith23:03:39

but usually if you have a seq of characters like that you started with a string, and that's something that can go to parseLong

theequalizer7323:03:00

I have this string “0011401780016X” and I would like to separate the last digit (which is always a letter) and the numbers to do some arithmetic operations

dpsutton23:03:47

(let [input "0011401780016X"] (Long/parseLong (subs input 0 (dec (count input)))))

3
theequalizer7323:03:56

Got it with subs and nth

dpsutton23:03:15

just beware of empty strings. subs can be brutal

theequalizer7323:03:17

I’m performing a regex validation before I get to this point, thank you

👍 3
hiredman23:03:49

reduce would be more fun

hiredman23:03:19

user=> (reduce (fn [n digit] (+ (* n 10) (Character/digit digit 10))) 0 '(\0 \0 \1 \1 \4 \0 \1 \7 \8 \0 \0 \1 \6))
11401780016
user=>