Fork me on GitHub
#beginners
<
2019-11-14
>
sova-soars-the-sora00:11:28

Compojure is awesome, but i'm trying to serve private files to some authenticated users

sova-soars-the-sora00:11:43

without the whole world being able to see the files

sova-soars-the-sora00:11:29

i'm trying to use two separate (route/files "members") and "pubic" in my auth routes and no-auth routes, but no files get found in my members directory

sova-soars-the-sora00:11:52

mm i'm going to try route/resources again and see if i can arrange it correctly.

sova-soars-the-sora00:11:59

a delicate arrangement, ye middleware!

sova-soars-the-sora00:11:43

figured it out. I made a specific resource response for just the particular route and it's a subset of the auth routes branch

(GET "/members/:filename" [filename :as r]
    ;(println filename)
  		(response/resource-response (str "members/" filename))))

noisesmith00:11:05

you can also provide a prefix to multiple wrap-resources invocations then use a different auth middlelware on each one

solf08:11:01

Do you use :refer :all in test files? That's what I see most in testing tutorials, but I'd rather not do it (plus clj-kondo throws a warning for those). I'd rather do [clojure.test :refer [deftest is testing] and [com.package.core :as core], thoughts?

solf08:11:35

For example here (https://github.com/clojure-cookbook/clojure-cookbook/blob/master/10_testing/10-01_unit-testing.asciidoc) they say:

;; The corresponding test in namespace com.example.core-test
(require '[clojure.test :refer :all])

;; In a real test namespace, you would also :refer all of the target namespace
;; (require '[com.example.core :refer :all])

salam08:11:26

we use the following convention at work:

(ns com.example.core-test
  (:require [clojure.test :refer [deftest is testing]
            [com.example.core :as uut]])) ; unit under test

solf08:11:20

that's interesting, thanks

borkdude08:11:52

There is no need for refer all or use really. IMO it results in guessing where all the names are coming from

borkdude08:11:06

And CLJS doesn’t support it

solf08:11:42

Yeah, I agree with that. I wanted to have more opinions as I don't want to impose my own preferences to the rest of the team, but I think I'll go ahead with deftest is testing

Andrea Imparato08:11:45

hello, anybody knows if it’s possible to use multiple repls with cider? I can’t find info on google 😕

Andrea Imparato09:11:20

nvm, i’ve found what i was looking for (here http://www.pitheringabout.com/?p=1030)

indy10:11:02

I want to learn a front-end framework, which one should I choose? Re-frame or fulcro?

sysarcher11:11:05

reagent?? I am on my 7th day and I didn't even know HTML/CSS before that... and now, I can create relatively good SPAs

sysarcher12:11:03

can someone help me out? https://clojureverse.org/t/cljs-use-apply-to-draw-image/5095 I'm trying to figure out why apply draw [vec-of-strings] isnt' having the same affect as a for [x [vec-of-strings]] (draw x)

👌 4
sysarcher12:11:32

I'd love to be even more concise 🙂 I think for x, do z loop doesn't communicate code as well as (apply function data)

herald12:11:24

You can do (map draw [vec-of-strings]). That will return the same as your for but be as short as how you want it done with apply.

aisamu13:11:41

Done! Do not hesitate to ask for clarifications 🙂

mfikes13:11:29

If you aren’t seeing the effect at all, for is lazy; try doseq instead.

mfikes13:11:35

(Oh, I see your problem is more fundamental.)

sysarcher14:11:30

@U1UQEM078 @UCW9TUDNK and @U04VDQDDY thanks a lot! I understand apply better now 🙂 thanks a bunch

🎉 4
sysarcher14:11:10

idk why I wasn't getting the idea completely... aisamu's explanation was good there

sysarcher14:11:41

btw, does map guarantee order of application? I mean, dev-1 before dev-2 before dev-3?

👍 8
jaihindhreddy14:11:56

@UPEGYT4G4 Short version: yes. Long(er) version: If you look at (doc map) it says map returns a lazy sequence. When you find the word sequence (or seq) in Clojure-land, it means a very specific thing. It means something that implements the interface clojure.lang.ISeq, which guarantees order. Check out https://clojure.org/reference/sequences But of course, this is about the return value. The other thing that the docstring says is that it returns a lazy sequence. Lazy means work happens only when accessing the output, and the only way to access the output is sequentially (because all you get is an ISeq), which also means the application happens in order as well. One other thing to be wary of is that, this doesn't mean if I ask for one thing, the function is applied only on one thing. Run (first (map println [1 2 3 4])) in your REPL. This is because map does the application in chunks for efficiency. Side effects in mapping fns is undesirable (in most cases) for this reason.

👍 4
David Pham13:11:34

Can someone help me on the argument of Clojure to integrate it into a JVM environment? “It is just a jar”. I know it can interop well with the Java and write better Java than Java, but at some point your colleague will see that you write Clojure code, right? I am trying to sneak Clojure in my company haha

etiago14:11:09

My advice: don't do it. Not in a "sneak it in" sort of way. Think of the bus factor [1]. If you're the only one who can maintain that piece of code, it's not considerate towards the rest of your team. [1] - https://en.wikipedia.org/wiki/Bus_factor

💯 4
chepprey14:11:23

Are your programmer coworkers also sympathizers, and the "sneaking" is only from the point of view of management?

etiago14:11:49

If you're a small team, try to persuade your colleagues by showing them how awesome Clojure is. If they're not having any of it, their loss, but still, not fair to just sneak it in IMO 🙂

✔️ 4
chepprey14:11:53

I would start by getting the other programmers to agree with your desire.

4
chepprey14:11:50

I undertook a similar black-ops mission about 6 years ago. I started by holding lunchtime meetings w/ other devs, showing them videos like Rich's "Are We There Yet" and other high-level Clojure introductions,

chepprey14:11:36

I talked about specific subsystems of our product where we REALLY could benefit from a) rewriting b) ... in a language like Clojure

chepprey14:11:16

I was a bit disheartened, actually, to discover that more developers than I expected were not enthralled with the idea. They were comfortable and familiar with Java/OOP and were uninterested in taking such a radically different approach to coding.

chepprey14:11:40

So I knew I'd have to play "the long game" with them. But then our company was acquired by a huge company and Java/script are the only permissable languages. :man-shrugging:

herald14:11:34

@UHL84CDTP Darn, I'm impressed you made such an effort over a long time though. I just quit and found a clojure job [x

David Pham15:11:46

I think the other devs don’t really care because I would be the one maintain it anyway.

mruzekw15:11:34

Is there a way to output in the REPL which symbols are available to call/use?

mruzekw15:11:56

It’d be nice to have a list of things, rather than guessing and checking every symbol

enforser15:11:10

I’m guessing you mean all of the vars defined in a namespace? If so, you could take a look at clojure.repl/dir

=> (dir clojure.string)

mruzekw16:11:12

Thanks, I will try these out

pavlosmelissinos16:11:06

Good morning! Could somebody explain the following head-scratching behaviour to me? I'm aware of the first one but the others seem weird to me...

(= ##NaN ##NaN)
=> false

(not (= ##NaN ##NaN))
=> true

(not= ##NaN ##NaN)
=> false

(let [x ##NaN]
  (not= x x))
=> true

mruzekw16:11:05

Are you ultimately looking to check if a value is NaN?

pavlosmelissinos16:11:51

Yup. I ended up using Double/isNaN so it's not an issue anymore but I'd still like to understand why this is the proper behaviour. 🙂

mruzekw16:11:23

kk, was going to suggest js/isNaN

mruzekw16:11:47

Ohh, you’re probably working in CLJ.

Alex Miller (Clojure team)16:11:13

##NaN is identical to itself, but not equal to itself

Alex Miller (Clojure team)16:11:48

due to various shortcuts for checking identity when checking equality, you can see weird results

Alex Miller (Clojure team)16:11:35

the key is, don't ever check ##NaN for either, use (Double/isNaN ##NaN)

👌 4
pavlosmelissinos16:11:05

Thanks a lot for the explanation 🙂 The implementation of not= appears to be identical to (not (=.... Do they also give different results due to one of the shortcuts that you mentioned? Something that happens in between?

andy.fingerhut16:11:32

In some cases a speed optimization is used to compare two objects using identical? and ##NaN is read by the Clojure reader always as the same object, identical to all others.

andy.fingerhut16:11:20

You may also want to search this guide article for occurrences of NaN, and recommendations for its use (or rather, avoiding its use for some purposes) in Clojure: https://clojure.org/guides/equality

andy.fingerhut16:11:35

Looking at your original 4 expressions, I do not at this moment have a reasonable explanation for why (not= ##NaN ##NaN) returns false, given the definition of not=. I may spend a few minutes investigating to see if I can learn why.

chrisn16:11:42

It is also possible to use Double/isFinite to check for both nan and inf values.

👍 4
andy.fingerhut18:11:44

Yeah, I don't understand in detail why (not= ##NaN ##NaN) is odd there (unless it is in my batman repo and I've forgotten). Alex Miller's advice is sound: do not rely upon ever comparing ##NaN to any other value, and getting back a particular result. Or rather, assume it will always return a value you do not expect.

andy.fingerhut18:11:11

I think I already did figure it out in detail. It and a bunch of other explanations of behavior can be found in the batman repo here: https://github.com/jafingerhut/batman/blob/master/doc/ubuntu-18.04.2-jdk-openjdk-11.0.3-clojure-1.10.1.txt

👍 4
pavlosmelissinos06:11:24

Thanks a lot for writing it all down, the repo seems super useful 🙂 Like I said on another thread, I did use Double/isNaN to circumvent this behaviour. Once again, thank you both for taking the time to investigate/explain. I really appreciate it as a member of this community! Some additional context in case anyone would like to know the whole picture: I'm collecting a bunch of stats into a map, so I've written a unit test to compare the expected output map with the actual one. Unfortunately, the stats library I'm using sometimes returns NaN for those stats and (is (= actual expected)) simply wouldn't work for NaN vals... I ended up using reduce-kv in conjunction with Double/isNaN to convert all the NaNs to nils

rschmukler17:11:11

Is there a way to pin key-value pair types in spec? eg. If I have a map where the keys might be ints or strings, but all keys that are ints have values that are ints and all keys that are strings have values that are strings? Kind of a s/merge across s/map-of?

Alex Miller (Clojure team)17:11:57

the best way to do that is to spec the map as a collection of kv tuples

Alex Miller (Clojure team)17:11:15

and then spec the tuple as s/or of [int? int?] or [string? string?]

Alex Miller (Clojure team)17:11:11

(s/coll-of (s/nonconforming (s/or :i (s/tuple int? int?) :s (s/tuple string? string?))) :into {})

Alex Miller (Clojure team)17:11:40

^^ that will conform and gen

rschmukler17:11:10

@alexmiller brilliant! Thank you for the help!

Alex Miller (Clojure team)17:11:30

have been down this road before :)

Alex Miller (Clojure team)17:11:55

this is how s/map-of is implemented too, so it's just getting in the middle of that

rschmukler17:11:11

Nice nice, makes a ton of sense now that I see it

rschmukler17:11:21

One more question - is it possible to mutual exclusion of keys in a s/map? eg. will have a :person/full-name or a :person/name but not both?

rschmukler17:11:44

(and I want s/valid? to reject any map that has both)

rschmukler17:11:14

Should I just use a (s/and (s/keys ...) validator-fn)?

Alex Miller (Clojure team)17:11:53

and that's probably best

rschmukler17:11:14

Is there any way to provide additional data when failing a predicate?

rschmukler17:11:29

ie. ideally I'd be able to provide rich data for explain-data

Alex Miller (Clojure team)17:11:37

no, that's something I've been thinking about

rschmukler17:11:55

Cool - well a +1 on the use case 🙂

Mario C.19:11:51

is it bad practice to write a small named function within a let-block to be used only within its scope? Or is better to define it at the top level?

Mario C.19:11:22

(let [show-text? (fn [show?] (if show? "Y" "N"))] ...)

Lennart Buit19:11:15

there is letfn for anonymous functions. For me, its a bit of a tradeoff: useful when you are certain you are not reusing the function.

noisesmith19:11:57

IMHO letfn is mainly useful for mutual recursion of named anonymous functions

Lennart Buit19:11:54

but this is a named ‘anonymous’ function right

Mario C.19:11:58

interesting, didn't know about letfn

noisesmith19:11:52

@dpsutton I know that's amusing, but since we are in #beginners I will mention that "named anonymous" is a thing in clojure, and is useful

👍 4
seancorfield19:11:58

For something that small, I probably wouldn't bother defining a local function unless it is used in several places (and then I might be suspicious that it perhaps ought to be mapped over a sequence of things).

👍 4
noisesmith19:11:45

with a name, the fn has a readable element to its printed represention, which makes stack traces slightly easier to deal with

(ins)user=> (fn [x] 1)
#object[user$eval142$fn__143 0x640f11a1 "user$eval142$fn__143@640f11a1"]
(ins)user=> (fn foo [x] 1)
#object[user$eval146$foo__147 0x64a8c844 "user$eval146$foo__147@64a8c844"]

☝️ 4
Mario C.19:11:12

I have something like this

(defn add-flex-text
  [response decision]
  (let [atts                     (:attributes decision)
        payments-due             (:_payments-due atts)
        show-text?               #(if % "Y" "N")
        program-name             (:program_name decision)
        accepted-program-is?     (partial = program-name)
        accepted-program-one-of? (partial some accepted-program-is?)
        sale-programs      ["_Silly-Program-Name" "_Serious-Program-Name"]]
    (->> {:FlextText1 (show-text? (<= payments-due 1))
          :FlexText2  (show-text? (and (>= payments-due 2) (accepted-program-is? "_No-program-accepted")))
          :FlexText3  (show-text? (and (>= payments-due 2) (accepted-program-one-of? sale-programs)))
          :FlexText4  (show-text? (>= payments-due 2))
          :FlexText5  (show-text? (accepted-program-one-of? sale-programs))}
         (merge response))))

Lennart Buit19:11:28

Slightly off-topic, but did you know: You can use sets as functions to test whether a value is member of that set:

(#{:a :b :c} :a)
=> :a
(#{:a :b :c} :d)
=> nil
So for example, you could use that for accepted-program-one-of
(let [valid-sales-programs? #{"_Silly-Program-Name" "_Serious-Program-Name"}]
  {...
   :FlexText3  (show-text? (and (>= payments-due 2) (valid-sales-programs? program-name)))
   ...})

Mario C.19:11:21

Yea I could have used sets but my reasoning was that if I used the sets then that function is tied to the specific set whereas I can re-use the non-set method with any collection of program-names.

Mario C.19:11:58

Idk I guess its the same thing

Lennart Buit19:11:54

well; you are not passing in the program names so far, and if you do, you can convert it to a set 🙂.

Lennart Buit19:11:40

anyhow; just a suggestion 🙂

hiredman19:11:17

anonymous function is just a flawed term

hiredman19:11:06

it is a result of a bad understanding of functions as values, so you get weird nonsense out of it, like "named anonymous function"

hiredman19:11:33

a value can be bound to any number of names in an number of scopes at anytime, and the set of names it is bound to may change as a program runs, so calling any kind of value "anonymous" is just weird

seancorfield19:11:39

@mario.cordova.862 You have a typo in that first key :FlextText1 instead of :FlexText1

Mario C.21:11:31

Good catch!

seancorfield19:11:19

Given that you're applying show-text? as a transformation to that whole map I'd probably do it in a reduce-kv pass (also, ? on a function generally signifies that it returns a strictly Boolean value -- true or false -- so show-text? is not an idiomatic name for that):

(->> {:FlexText1 (<= payments-due 1)
          :FlexText2 (and (>= payments-due 2) (accepted-program-is? "_No-program-accepted"))
          :FlexText3 (and (>= payments-due 2) (accepted-program-one-of? sale-programs))
          :FlexText4 (>= payments-due 2)
          :FlexText5 (accepted-program-one-of? sale-programs)}
         (reduce-kv (fn [m k v] (assoc m k (if v "Y" "N"))) {})
         (merge response))

👍 4
sysarcher20:11:42

Hello people... is there some project on Github that gives info about how how testing works? I created my first site in Clojurescript but I want to be able to exercise all the API requests it makes. Speaking of API requests, what's the most "Clojurescript" way to pass the server URL/auth to the code? It might be aquestion in general for Frontend development too... How is the address of the api backend stored? I created a client that can talk to any api-compatible backend.. Do we ask this URL of users everytime (I'm thinking mattermost-style dialog boxes.. mattermost can talk to it's backend instances hosted anywhere)? Is there somewhere we can put a config file? Are cookies the best way?