Fork me on GitHub
#beginners
<
2018-11-24
>
beders00:11:51

i.e. someone passes me either a [:h1 "bubu"] or a [:h1 {:style ""} "bubu"]

beders00:11:26

and I need to turn this into a [:h1 {id: "some-id"} "bubu"]

seancorfield00:11:26

It always has either two or three elements? Maybe destructuring would be easier here

(defn add-id [[tag attr-or-body body] the-id]
  (into [tag] (if body [(assoc attr-or-body :id the-id) body] [{:id the-id} attr-or-body]))))
then you can just call (add-id hiccup-data "some-id")

enforser00:11:48

Can't hiccup have more than two parameters though?

beders00:11:09

yes, there can be any number

beders00:11:05

Ok, I think I got something that works, but it sure looks ugly 🙂

(defn add-id [field-html id]
  (let [[element & rest-elements] field-html
        [attr body] (if (map? (first rest-elements))
                      [(first rest-elements) (rest rest-elements)]
                      [{} rest-elements]
                      )
        ]
   (vec (concat [element (assoc attr :id id)] body)))
  )

beders00:11:44

and doesn't generate a vector yet

enforser00:11:15

(defn foo
  [[tag attr-elem & elems]]
  (if (map? attr-elem)
    (concat [tag] [(assoc attr-elem :id :some-id)] elems)
    (concat [tag {:id :some-id} attr-elem] elems)))

beders00:11:18

thank you!

beders00:11:48

I hope I can shake that feeling eventually that some things that are "easy" in Java are hard in clojure 😉

andy.fingerhut00:11:24

If your level of Java familiarity is much higher than Clojure, then that feeling can take a while to shake. It is a learning experience.

👍 4
enforser00:11:30

right you are about the concat

enforser00:11:39

(defn foo
  [[tag attr-elem & elems]]
  (into [tag]
        (concat (if (map? attr-elem)
                  [(assoc attr-elem :id :some-id)]
                  [{:id :some-id} attr-elem])
                elems)))

beders00:11:10

thanks again for the quick help. I need to go easy on those left-overs

beders00:11:18

Clojure community rocks!

dpsutton01:11:25

i feel like there is a monadic solution to this one as well. this sounds like an either or some kind of state monad could work

beders02:11:59

probably also doable with a pattern matcher

beders03:11:12

as usual, if things tend to become too complicated, the approach is probably wrong. Turned out that normalizing the structure first, then manipulating the second element is much easier. Good lesson.

4
codecitizen15:11:53

I can't seem to find any option/environment variable that allows me to change the Java Path / Java Home for the clojure script. Could someone point me to the proper documentation?

andy.fingerhut15:11:46

The clojure script I have does not set the JAVA_HOME env variable, but expects it to have a value already set when it starts. If you use the bash shell (or several others with similar command syntax) you should be able to first do export JAVA_HOME=/path/to/my/java

👍 4
codecitizen16:11:16

Thank you @andy.fingerhut! Yeah just figured that out too. Simply setting JAVA_HOME is enough 🙈

adam17:11:37

My Clojure functions seems to be called at the same time. Aren't function supposed to be called one after the other when they are on the same file in Clojure?

daniel.spaniel17:11:59

I was trying to practice using match ( from examples on the web like )

daniel.spaniel17:11:00

(let [x true y true z true] (match [x y z] [_ false true ] 1 [false true _ ] 2 [ false] 3 [ true ] 4 :else 5))

daniel.spaniel17:11:14

and i get Caused by: java.lang.RuntimeException: Unable to resolve symbol: match in this context

lilactown17:11:09

match isn’t part of the Clojure core. You have to include core.match as a dependency

daniel.spaniel17:11:33

i will give that a shot

daniel.spaniel17:11:08

thanks .. that worked to require it in my project.clj file.. gosh .. i am the unlimate noob ..

lilactown17:11:10

no problem 🙂 it is confusing

lilactown17:11:31

match is something that you would expect to be in clojure.core, but Rich Hickey has opinions about pattern matching

daniel.spaniel17:11:11

i read something about that where Rich was saying he did not like certain kinds of pattern matching. i liked the erlang style function patter matching and i was trying to experiment with working on how to do that

lilactown17:11:33

I really like Erlang’s pattern matching as well. it is very convenient

daniel.spaniel17:11:26

i saw that library called defun but i not sure if anyone using it or that if that is kinda frowned on ( in favor of using the match function )

lilactown17:11:55

oh neat. I haven’t seen that before

lilactown17:11:21

Clojure has multimethods which are kind of a rough approximation of certain kinds of Erlang pattern matching

daniel.spaniel17:11:29

i was reading about that too .. i don't mind doing stuff that is not idiomatic clojure but it is nice to know what other people do to solve that kind of problem

daniel.spaniel17:11:58

i am curious how to run that ( i am using lein repl and also regular closure cli

andy.fingerhut17:11:02

@somedude314 Functions are supposed to be called one at a time, per JVM thread at least, no matter whether they are in the same file, or different files. What have you tried that leads you to think it might not be doing that?

daniel.spaniel17:11:48

i think i am pretty up to date with clojure with

daniel.spaniel17:11:49

REPL-y 0.3.7, nREPL 0.2.12 Clojure 1.8.0

andy.fingerhut17:11:52

But note that if function A calls function B, then in one sense A and B are being called "at the same time", overlapping in time. That is not unique to Clojure.

manutter5117:11:12

@dansudol You might need to do (require '[core.match :refer [match])?

daniel.spaniel17:11:19

ok ..trying that

daniel.spaniel17:11:56

i tried to require core.match and now get

daniel.spaniel17:11:57

Could not locate clojure/core/match__init.class

lilactown17:11:13

you need to install the dependency into your project

daniel.spaniel17:11:16

i guess i have to install core.match or something ?

daniel.spaniel17:11:47

oh .. ok .. i thought something like core.match was part of the core package. most of the examples on teh web make it look like that

lilactown17:11:21

nope. it is a separate library

adam17:11:31

@andy.fingerhut here's my code https://bpaste.net/show/22941769984b - they are working 100% of the time when I call (setup-db-tables! "drop") and (setup-db-tables! "create") separately. If I call them together, it's as like the tables are not given enough time to get deleted.

andy.fingerhut17:11:58

A quick note, before understanding all of your code, but maybe the root cause of issues you are seeing: for in Clojure is lazy. It returns an unevaluated lazy sequence, which is not evaluated until and unless something "forces" the elements of the lazy sequence to be realized.

andy.fingerhut17:11:05

Maybe you might want doseq there instead

andy.fingerhut17:11:19

doseq is "eager"

adam17:11:01

@andy.fingerhut that solved the issue! Thank you.

Kari Marttila17:11:14

I'm wondering what could be an elegant way to provide support for new data sources processing based on the profile the program is running with. E.g. If I have several profiles in my profiles.clj, e.g. :local, :remote-A, :remote-B etc (which provide e.g. :endpoint to the service I request the data). Then I should be able to define dispatching based on the profile we are running and when I call e.g. (get-data) this method would dispatch based on the profile (i.e. using the :endpoint and the processing also is a bit different for various data sources). Multimethod so that I define some auxiliary multimethod "internal-get-data" with dispatching using some data which comprises the profile (or some environmental data in that profile)? Pseudocode: (defn get-data [] (internal-get-data <some-dispatching-data>)) i.e. <some-dispatching-data> => provides the information for the dispatching?

daniel.spaniel17:11:16

any cursive users out there feel like giving me a hand. i am loath to admin it, but i am mostly lost trying to set it up .. i have gotten somewhere but need help on getting really going

rakyi17:11:55

I’m not a Cursive user, but you might be able to get more help in #cursive

daniel.spaniel17:11:12

oh .. thanks did not know that existed

Kari Marttila17:11:22

I use cursive, it's great. I can try to help.

daniel.spaniel17:11:58

man .. i be desperate .. i just can;;t figure it out and i keep re reading the docs over and over again

Kari Marttila17:11:15

Let's go to #cursive and continue there...

Kari Marttila17:11:46

BTW, how do you go there? 🙂

daniel.spaniel17:11:31

a friend who uses clojure told me about this channel ( he uses emacs )

Kari Marttila17:11:04

I mean I can't find the channnel in this Clojurians slack...

enforser17:11:14

click on #cursive

enforser17:11:28

or click on "Channels" and find cursive

Kari Marttila17:11:37

Ok. I found it now, let's go there.

lilactown17:11:44

FYI I think Cursive just released a new version and they’re in the midst of updating the docs?

daniel.spaniel18:11:14

gosh .. i hope they update the docs .. man .. i just stare at them mystified because it does not match the current version

daniel.spaniel18:11:58

wow .. that is timely .. thanks

lilactown18:11:05

it’s very unfortunate that they would release the new version without updating the documentation. I’ve sent one or two PRs myself to update their docs (and I don’t even use Cursive day-to-day)

daniel.spaniel18:11:25

ok .. that is pretty hillarious

Karol Wójcik18:11:27

Hello 🙂 This is my first time trying to fix reflection warnings therefore help is welcome 😛

(def ^HmacUtils gh-sha1-generator
  (^HmacUtils HmacUtils. HmacAlgorithms/HMAC_SHA_1 (:github-webhook-secret envs)))
I’m receiving the following warning:
Reflection warning, codcheck/auth.clj:14:3 - call to org.apache.commons.codec.digest.HmacUtils ctor can't be resolved.
What is a correct way to fix it?

Karol Wójcik18:11:57

Ok I got it. All I had to was to add type annotations for ctor args.

(def ^HmacUtils gh-sha1-generator
  (HmacUtils.
   ^HmacAlgorithms HmacAlgorithms/HMAC_SHA_1
   ^String (:github-webhook-secret envs)))

Karol Wójcik18:11:38

Btw what do you guys do with reflection warnings in 3rd party libraries? I mean how do you disable them

lilactown18:11:38

you can set a global on/off whether to warn on reflection

lilactown18:11:55

ideally, though, the library would be updated to fix the reflection warnings

andy.fingerhut19:11:30

If reflection occurs in non-critical-path code, e.g. init code intended to be run once or a few times in your application, it is perfectly reasonable to leave it there. Clojure itself has dozens of occurrences of reflection in its implementation like this.

Karol Wójcik19:11:17

But shouldn’t we remove those warnings? I mean Clojure and Library maintainers should either remove those warnings or allow community to do it.

Karol Wójcik19:11:51

For instance I’m preparing the PR for buddy.sign. I think it’s important because for instance Graalvm requires no warnings as far as I can tell

andy.fingerhut19:11:11

If they aren't hurting performance in a significant way, I'd say no. Also some reflection warnings are impossible to remove with type hints.

andy.fingerhut19:11:44

e.g. if the run time type is truly unknown at compile time on a Java interop call, and must be resolved at run time.

andy.fingerhut19:11:28

When compiling Clojure, there are no reflection warnings, because the places where reflective calls exist, (set! *warn-on-reflection* true) has not been done in that file, so the compiler issues no warning.

andy.fingerhut19:11:56

If there is a reflective call in the inner loop of some performance-sensitive part of a library, I'd say that is a performance bug, yes.

Karol Wójcik19:11:22

Ok now I got it. There are so many things I don’t know about Clojure/Jvm ecosystem. Thank you @andy.fingerhut for clarification. 🙂

andy.fingerhut19:11:43

Everything is new to a person once. No worries.

adam20:11:01

How can I make this function work when its comment has quotes: (defn hi "not w"k"ing" [] "hello") without escaping every quote?

adam20:11:36

(comment ...) is not working

adam20:11:28

(defn hi (comment "not w"k"ing either") [] "hello")

lilactown20:11:43

you have to escape them

adam20:11:22

@lilactown Ah okay, thanks

andy.fingerhut20:11:48

If you want it to be a doc string, yes. You can comment lines with ';' of course, no quote escaping required there.

adam22:11:45

@andy.fingerhut gotcha, ; didn't cross my mind in this case, will use it

jstaab22:11:55

Hey all, I've used the ramdajs library for a long time, and now that I'm working in clojurescript, I find myself often reaching for (and manually writing) ramda functions, but I'm curious if that's an antipattern? Like, should I be investing more time in understanding transducers, or using spectre? I know ramda's auto-curried approach isn't really clojure's jam (which is cool, because in clojure it's rarely necessary), but things like a.filter(whereEq({x: 1, y: 2}) are so handy to have around. Should I discipline myself to use clojure's idioms, or is ramda (via cljsjs maybe) an ok way to go?

lilactown22:11:37

I would definitely suggest against actually using the ramda js library

jstaab22:11:58

Are you thinking idioms, performance, bloat?

lilactown22:11:57

it’s non-idiomatic, not portable, performance will be worse than native JS or it just straight up won’t work with Clojure data structures

jstaab22:11:48

I'm curious what's not idiomatic about it, for example how might you do (some (where-eq {:x 1 :y 2}) xs) in vanilla clojure?

lilactown22:11:52

I don’t think you really need transducers or specter to reproduce a lot of what ramda gives you

jstaab22:11:42

Best I can come up with is (some #(and (= (:x %) 1) (= (:y %) 2)) xs) which is pretty ugly

lilactown22:11:58

sure, creating your own where-eq is probably better(ish)

lilactown22:11:15

there might be ways to code-golf that down but giving it a name is also nice

jstaab22:11:48

Yeah, the name and simple structure makes it very easy to read

jstaab22:11:16

interesting, maybe I'll just start porting ramda to clojure then, I use probably 30% of the library (but it's huge)

lilactown22:11:47

a lot of what ramda gives you is already in Clojure though

jstaab22:11:51

That's true

lilactown22:11:05

lazy sequences, chaining, etc.

jstaab22:11:11

And the whole iteratee-last style in ramda isn't necessarily relevant in clojure everywhere

jstaab22:11:43

e.g. assoc is switched

lilactown22:11:06

Clojure optimizes over a couple of different things when it comes to order

lilactown22:11:19

for a lot of things (e.g. assoc) it’s optimized for thread-first ->

jstaab22:11:29

Yeah, it used to be weird to me, but it's definitely thought through

jstaab22:11:40

Related question though, what if you want to thread, but use some, then assoc?

jstaab22:11:58

You can't use thread-first because of some's signature, or thread last because of assoc

lilactown22:11:05

annoyingly, sequence operations are often reverse (e.g. map, filter) because if you pass in only a predicate it returns a transducer

lilactown22:11:25

yeeeppp. in those cases, I use as->

enforser22:11:12

as-> or for simple cases I do things like:

(-> x
    (->> (some pred?))
    (assoc key val))

jstaab22:11:15

Oh wow that is a cool macro

jstaab22:11:49

Thanks all, I will not use ramda, instead I will port concepts over in an ad-hoc, clojurey way until I grok the idioms better.

4
rakyi22:11:07

there are some utility libraries around like https://github.com/weavejester/medley

Nolan22:11:33

Hi, I just installed clojure 1.9. When I try to run clj at command line, I get what I believe is a proxy issue, something about failed to read artifact descriptor. Any ideas?