Fork me on GitHub
#beginners
<
2018-06-15
>
johnj00:06:10

rest forces the realization of at least one value in a lazy-seq correct?

noisesmith00:06:23

no, but next does

noisesmith00:06:41

oh, wait, yes, and next forces at least two

noisesmith00:06:55

Clojure 1.9.0
+user=> (def loud-nils (map println (iterate inc 0)))
#'user/loud-nils
+user=> (def r (rest loud-nils))
0
#'user/r
+user=> (def loud-nils' (map println (iterate inc 0)))
#'user/loud-nils'
+user=> (def s (next loud-nils'))
0
1
#'user/s

noisesmith00:06:01

yes, the head

noisesmith00:06:23

next also checks the first item of the tail (but you weren't asking about next)

johnj00:06:15

Ok, rest skips the head

johnj00:06:52

what's the rationale of this? rest vs next

noisesmith00:06:52

next promises to return nil if the tail is nil, rest can return an empty list instead

noisesmith00:06:00

the behavior of next is often useful in conditionals

johnj00:06:24

to avoid using empty? for example?

noisesmith00:06:03

or seq (to get a nil for an empty input, thus your false case)

👍 4
teodorlu07:06:55

Moved the leiningen question above to #leiningen .

joshkh09:06:15

my java interop skills are lacking.. how can i go about passing one of these constants (Regions.EU_WEST_1) into a constructor?https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/regions/Regions.html

joshkh09:06:28

never mind, problem solved. 🙂

(import com.amazonaws.regions.Regions)
=> com.amazonaws.regions.Regions
Regions/EU_WEST_1
=> #object[com.amazonaws.regions.Regions 0x2bf311c7 "EU_WEST_1"]

cristibalan13:06:40

Hi. I'm trying to use thrown? to check for an exception, but the is still fails because of it. I get a stack trace even from the example in the documentation: (is (thrown? ArithmeticException (/ 1 0))). I'm trying this with vim-fireplace, btw. Any ideas?

cristibalan13:06:55

I'm getting this as the output:

#error {
 :cause "Divide by zero"
 :via
 [{:type java.lang.ArithmeticException
   :message "Divide by zero"
   :at [clojure.lang.Numbers divide "Numbers.java" 163]}]
 :trace
 [[clojure.lang.Numbers divide "Numbers.java" 163]
...

taylor14:06:13

do you mind posting your whole test?

cristibalan14:06:24

Hi. This raises the above for me:

(deftest foo-test
 (testing "foo foo"
   (is (thrown? ArithmeticException (/ 1 0)))))

cristibalan15:06:46

It seems it's vim-fireplace related somehow. Just tried and tests pass on the command line.

taylor15:06:17

yeah that test looks correct :man-shrugging:

4
mfikes16:06:14

@nicki One thing you will often see is or being used as in

(let [user {:real_name "real" :display_name "my name"}
       display-name (:display_name user)
       real-name (:real_name user)]
  (or (not-empty display-name)
      real-name))

👍 4
justinlee16:06:23

one other thing: in real code you’d obviously be given user and you’d probably want to destructure it like this (let [{:keys [display-name real-name]} user] ...

mfikes16:06:37

It seems a little odd to me to apply not-empty to a non-coll. Hrm.

dpsutton16:06:22

probably want clojure.string/blank? ?

👍 4
justinlee16:06:38

as for your second question, I think it’s something reasonable people can disagree upon, but I’d say generally code is written with some assumptions about what is inputs are ok. if you write every function defensively your code becomes hideous. you can either add assertions or use spec or schema to do some sort of validation to assist in tracking down bugs, though. (this is obviously different if you are doing i/o, when you’d want to write code that is prepared to deal with anything)

mfikes16:06:02

Yeah ^ perhaps the use of spec in modern code, in this case constraining the value that :display_name can take, would be sufficient

dpsutton16:06:20

I like to make sure there's one and only ever one function that will get you the user information. And then in that function you can put whatever defensive logic you want. Then consumers of the name know that it's been conformed and you don't have to be defensive elsewhere in your code base

dpsutton16:06:55

Conform in a non technical sense. Whether it's through spec conforming or just custom logic etc

mfikes17:06:00

@nicki Right, or composes nicely with not-empty

seancorfield17:06:07

That's why I like (or (not-empty some-string) other-string)

mfikes17:06:34

@seancorfield TBH, it is not clear to be whether not-empty is legit to apply to a string

dpsutton17:06:19

I would be surprised by it. At least at first. I look the blank check because it's very straightforward. No real chances for subtle bugs to lurk

dpsutton17:06:54

And it explicitly handles nil empty and " " in the way you want

dpsutton17:06:11

The not empty will fail on a string of space characters

dpsutton17:06:37

Although you're probably trimming at some point in this call stack

seancorfield17:06:08

True, it depends on whether you consider an all-whitespace string to be "empty" or not.

Nicki_Vance17:06:53

oh yeah, gotcha @mfikes, you're right, or definitely works with non-empty. i'm mixing my fixes.

seancorfield17:06:02

If :display-name is " ", you'll get different behavior from blank? vs seq/`empty?`/`not-empty`

dpsutton17:06:33

well not-empty will consider it "not-empty"

Nicki_Vance17:06:40

@seancorfield good point. i hadn't thought about " ", which could happen. in my scenario, i'd actually want to use " ".

dpsutton17:06:50

ah. well there you go

dpsutton17:06:23

i would make your own function that encodes this logic. (defn display-name [user] ...)

dpsutton17:06:28

and everyone calls that

8
dpsutton17:06:56

there you can be as clever as you want. clever code that you repeat everywhere can be buggy. clever code once is fine because you can put tests that show its exact behavior

Nicki_Vance17:06:40

cool, that makes sense

seancorfield17:06:42

(funnily enough, we have that exact function at work, because our dating site members can choose whether to use their username or their first name + initial on their profile)

Nicki_Vance17:06:26

haha, yes, i'm playing with the slack api, so very much the same

dpsutton17:06:32

then in the future this function gets extended to take a user-preferences map, context map, on and on

Nicki_Vance17:06:35

ah, so you get a different display name based on whether someone chooses to display username or their real name.

dpsutton17:06:41

yes. also context matters. maybe chat shows nickname but profile page shows full name. on and on. your user shouldn't care. consumer shouldn't care "give me a display name. use all the fancy tricks you like"

🌟 4
bortexz18:06:58

Hi, I have a macro that uses a vector to generate some code. But I’d like to reuse that vector somewhere else, so I try tried to define it in a symbol, but then the macro does not work with Don't know how to create ISeq from: clojure.lang.Symbol. Is there any workaround for this? The vector is going to be constant, so it could be evaluated compile time

dpsutton18:06:07

then just ~ it in your macro. but fundamentally macros work with forms not values.