Fork me on GitHub
#beginners
<
2018-07-19
>
jonahbenton00:07:57

about the nil, yeah, it's confusing. when you say (def ....) or (defn ...) a change is made to the namespace you're in, and those operations return the var, but different repl/client tooling has different ways of reporting that to you.

jonahbenton00:07:57

about the nil, yeah, it's confusing. when you say (def ....) or (defn ...) a change is made to the namespace you're in, and those operations return the var, but different repl/client tooling has different ways of reporting that to you.

noisesmith00:07:06

this is false, def and defn return a var, perhaps the elisp function in emacs is returning nil

jonahbenton00:07:31

woops, yup, of course, will edit

Chase00:07:53

i'm not quite able to follow this. when in spacemacs i say "cider-eval-last-expr" in the actual text file of the program right next to the expression it says => nil. it also says that at the bottom buffer line. but in the repl it says "choo choo" (no quotes) Now when I say "cider-send-last-expr-to-repl" the repl sends the whole expression and gives me Choo Choo on one line and nil under it.

noisesmith00:07:18

cider is not telling you what clojure returns

noisesmith00:07:17

I don't know why it gives you a nil, but clojure does not return nil if you run def or defn

Chase00:07:14

hmmm. when i do the same command on just (println "choo choo") it gives me => "choo choo" so not sure what is happening there

Chase00:07:47

it's weird when i run it on a defn it says nil in the file but the repl pops up the correct function evaluation at the same time.

jonahbenton00:07:05

so- there will be the repl protocol, and then there will be what gets written to "standard out"

jonahbenton00:07:23

(println "choo choo") will cause "choo choo" to get written to stdout. the function (println) doesn't have a return value

Chase00:07:11

ahhh! I think this is clearing up the mystery.

David Reno01:07:18

Some books/tutorials substitute the ‘str’ function for print. Try that and see the diff in spacemacs/cider maybe?

noisesmith17:07:25

everything in clojure has a return value, except throwing an exception or exiting the vm - println returns nil

Chase18:07:36

using str instead of println did do what I was expecting. thank you! i just need to grok more on what it means that println returns nil. it was all more of a curiosity about repl driven development and what info it gives you. thanks everybody for providing some clarity, there is so much more to learn!

Chase00:07:56

cool. that is what i was thinking. and someone recently gave me a lot of resources on repl driven development i still need to go through. i am curious. does the general work flow usually go you write a function or expression in your actual program file, send it to the repl to see if it works, and keep going? a lot of the tutorials seem to just be almost building the entire program in the repl itself but then am i supposed to go back and put those in the actual .clj file?

Chase00:07:26

i know this is probably super beginner stuff that i should just learn along the way but i needed a break anyways. sorry if this is too trivial for the beginner chat.

jonahbenton00:07:45

no no, that's exactly right 🙂

Chase00:07:46

which one? program file first, then to the repl or vice versa, build the function using the repl and then send that to the program file?

jonahbenton00:07:07

most folks do the repl first, then add it to the .clj

jonahbenton00:07:24

and then periodically "reload" the cljs that are part of the project

jonahbenton00:07:03

so that you can interact in the repl with the current way the program is structured across namespaces

Chase00:07:27

cool beans. it does seem like a fun way to develop.

noisesmith00:07:46

btw as I mentioned in a reply above, def and defn return vars, it must be some emacs function returning nil

Chase00:07:11

i've been debating which lisp family language to take a deep dive into first. I think i ultimately would want to use clojure for my projects but would it help to use something like racket's how to design programs, or SICP and scheme, or Practical Common Lisp to get a better foundation for programming before switching to Clojure? I'm using Clojure for the Brave and True right now, just not sure if it's recommended for a pretty new programmer to jump straight into clojure.

jonahbenton00:07:34

hard to say; it is definitely the case that clojure is intended for professional rather than educational use (though of course there are many teachers using it as a teaching language), while scheme and racket have more pedogogical and conceptual material supporting them

jonahbenton00:07:21

and clojure exposes one to more and more disparate things (mostly java related) which can definitely be distracting and confusing

Chase00:07:53

yup. but i'm hoping "developer motivation" can maybe see me through. i like using books so plan on using Brave and then Living Clojure. I guess if I just find it too difficult i can always switch gears. or maybe even after i get some clojure under my belt i can try to do something like the SICP text with clojure instead of scheme? that might get a little too hairy though.

jonahbenton00:07:55

yeah, would concur with hairy; one really wants to be able to exactly replicate the experience the book leads one through; there are all sorts of details in SICP that do not directly translate to clojure

dpsutton00:07:02

http://www.sicpdistilled.com/ only half completed but right up your alley

Chase00:07:39

cool! this is what I call a damned productive break!

dpsutton00:07:52

there's lots of cool stuff. @tbaldridge has video series on the compiler behind core async and a series on making a JIT. ccgrande made a vm to parse clojure forms with regexes. Clojure is great because it's still playful as a lisp and can get you a paycheck as well

Chase00:07:17

that last sentence is exactly why i wanted to do the deep dive in Clojure right away if feasible. especially with the potential for the full stack web app with clojurescript on the front end.

dpsutton00:07:04

this might be up your alley as well then https://learnreagent.com/

jonahbenton00:07:10

plenty of folks here to help you through!

Chase00:07:12

for something like reagent, is not knowing javascript and react really going to hurt me there? I guess people are able to learn clojure without knowing java so hopefully not.

Chase00:07:17

and when i start trying out clojurescript, if i can skip learning javascript, will i still want a very strong foundation in html/css? or is that part of clojurescript capability too?

jonahbenton00:07:06

my personal feeling is/advice would be- the sense that one has to understand the lower level stuff right away to learn the higher level stuff is- generally speaking, not to be trusted. you can totally learn clj and cljs without knowing java or js or css beforehand, and just fill in the gaps as you go. in reality that's what everybody does. in fact, working in the higher level of abstraction, achieving a certain level of mastery, then going down a level- this for me is much more satisfying. whole new insights open up about the higher level that previously was well known. on the other hand, when you're at a lower level just because, and you really want to be at the higher level- to me, that's kind of wasting time. ymmv.

jonahbenton00:07:26

that all said, one does see a lot of java in clojure, and a lot of js/etc in cljs- and seeing that stuff can be totally befuddling and frustrating. but it can be worked through.

Chase00:07:08

great response! You just alleviated a lot of anxiety I've had on my approach to this whole intellectual curiosity and desire to learn clojure. thank you!

jonahbenton00:07:06

glad to help, you're very welcome!

nakiya01:07:17

Doing SICP exercises with clojure. For exercise 1.24, here is the expmod function written in clojure:

(defn expmod [base exp m]
  (cond (= exp 0) 1
        (even? exp) (mod (expmod (square base) (/ exp 2) m) m)
        :else (mod (* base (expmod base (- exp 1) m)) m)))
Now, (expmod 189 1999 1999) throws ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1501) How do I tell clojure to use bignums in this case?

nakiya01:07:22

I tried the below and it doesn't work either (I get the same error).

(defn expmod [^BigInt base ^BigInt exp ^BigInt m]
  (cond (= exp 0N) 1N
        (even? exp) (mod (expmod (square base) (/ exp 2N) m) m)
        :else (mod (*' base (expmod base (-' exp 1N) m)) m)))

kennytilton01:07:46

@chase-lambert My experience? Reagent hides React very well. HTML and CSS are linear atrocities, so bearable, and massively documented.

nakiya02:07:28

(defn expmod [base exp m]
  (let [bibase (BigInteger. (str base))
        biexp (BigInteger. (str exp))
        bim (BigInteger. (str m))
        bizero (BigInteger. (str 0))
        bione (BigInteger. (str 1))
        bitwo (BigInteger. (str 2))]
    (cond (= (.compareTo biexp bizero) 0)
          bione
          (= (.compareTo (.mod biexp bitwo) bizero) 0)
          (.mod (expmod (bisquare bibase) (.divide biexp bitwo) bim) bim)
          :else
          (.mod (.multiply bibase (expmod bibase (.subtract biexp bione) bim)) bim))))
Yuck

nakiya02:07:38

Surely there should be a more concise way of coding this in clojure?

nakiya02:07:11

Or, doesn't clojure have language support for bigint / bignum?

nakiya02:07:49

My mistake. Second version works properly. I was calling it like this: (expmod 189 1999 1999) while I should have been calling it like (expmod 189N 1999N 1999N)

cristibalan11:07:18

Hi. Is there some idiom for this? (let [moo (if (funky? moo) (unfunk moo) moo)])

cristibalan11:07:18

Hi. Is there some idiom for this? (let [moo (if (funky? moo) (unfunk moo) moo)])

delaguardo11:07:08

Usually I do that. funky? returning moo if it is funky and after that just use if-let

henrik11:07:58

You can move the conditional into the unfunk function. (let [moo (unfunk moo)])

henrik11:07:00

You’ll have to determine if it’s useful to have to consider the funkiness at that moment, or if it’s better to hide it in the function. For example…

(let [a-string (if (untrimmed? a-string)
                 (trim a-string)
                 a-string)])
… would be silly.

val_waeselynck11:07:37

@U9N08C5HC (cond-> moo (funky? moo) unfunk)

cristibalan12:07:35

@U06GS6P1N Thanks! I knew I'd seen this before. I looked at cond-> but I discarded it because I thought I wanted a version where the moo gets passed through to the predicate as well. But I guess that doesn't exist because it would be mind twisting when having more than one condition.

cristibalan12:07:57

@U06B8J0AJ @U04V4KLKC Thanks. That is an option I tend to use, but in this case I'm actually using subs to unfunk and making an actual fn out of it is not worth it.

mfikes12:07:13

FWIW, Val's cond-> example is in fairly common use. (In fact, I suspect that cond-> may be used that way more often than to actually thread several things together.)

mg14:07:04

In the past I’ve written a function something like this:

(defn xform-if
  [x pred f]
  (if (pred x) (f x) x))
Allows for threading like with cond-> without repeating the threaded value in the condition, and also uses the current value… but mostly stopped using this kind of thing in favor of just cond->

jumpnbrownweasel15:07:48

seems like if-> would be a good name for that, do you think?

seancorfield15:07:39

We have a variant at work called condp-> (and condp->>) which thread through the predicates as well as the expressions. I think I've posted the code here a few times...?

val_waeselynck15:07:42

As soon as my code is going to be read by someone else, I tend to refrain from writing this sort of helper 🤔

seancorfield16:07:15

I think most Clojure shops have their own small library of such functions that they use liberally 🙂 But I agree that for a public OSS project, is perhaps less advisable... That hasn't stopped things like Encore etc being widely used tho'...

seancorfield16:07:04

(condp-> moo funky? unfunk) seems fairly intuitive to me tho' since it's not too far from the cond-> in core.

mg14:07:10

beginner top tip: use cool names for bindings if you want to get a lot of attention to your question 😄

dangercoder16:07:32

asked this question in the web-security channel but I think its quite dead (only 45 members). Is there any need for a "Security step" on the sign-up part of a web-app? I understand if you are logged in and u use tokens to see if ur a valid user. Unsure about the sign-up part though. The sign-up endpoint will only be accessable from localhost.

sveri16:07:15

@jarvinenemil What exactly do you mean with "Security step"?

dangercoder16:07:07

That's what I am trying to figure out. I created this sign up endpoint but since this is my internal api there should be no need for jws etc. I will have some api endpoints which 3rd parts will be able to access (Where i use jws)

jonahbenton16:07:18

Perhaps there are two questions: 1. does a registration flow have to be authenticated or otherwise protected from attack? 2. do any needed protections need to be applied to an api listening only on localhost?

adam18:07:20

What's up with threading in Clojure? I never had to deal - or understand threads - with JS/Python/PHP/... but everyday I see "thread-safe" etc. when working with Clojure. Why should I care about threads with Clojure?

manutter5118:07:37

The Java VM supports multiple threads — multiple different bits of code all running at the same time. A good example is a web server: the server spins up multiple threads, so that it can process multiple web requests at the same time.

manutter5118:07:37

The reason you should know/care about threads is if you ever use something that is not thread safe, you could have one thread trying to do something with some data, and have a separate thread accidentally writing its own data on top of what the first thread is trying to do.

hiredman18:07:30

you should know about threads if you are writing js, because odds are you are working on a website, so infact your distributed system is multithreaded

manutter5118:07:38

We had this recently with date formatting: we set up one global date formatter for all the threads to share, but it turns out date formatting is not thread-safe, so sometimes we’d get dates that were garbage strings.

adam18:07:52

I see. Thanks for the clarifications.

john18:07:15

This book also gives a good overview of how hairy multi-threaded programming can be: http://jcip.net/ (Java Concurrency in Practice)

zlrth18:07:59

in core.match, how do i match against a set of of args?

(let [apparel-clause '(:or "Baby & Toddler Clothing" ;; i also tried #{"stuff"....}
                                                     "Apparel & Accessories"
                                                     "Baby & Toddler Clothing Accessories"
                                                     "Clothing Accessories")
                                x               "Clothing Accessories"

                                ]
                            (match [x]
                                   [apparel-clause] "matched"))
doesn’t work. this does work:
(match [x]
                                   [(:or "Baby & Toddler Clothing"
                                         "Apparel & Accessories"
                                         "Baby & Toddler Clothing Accessories"
                                         "Clothing Accessories")] "matched")
but i’d rather abstract those 4 strings into a binding

Josh Horwitz19:07:11

I’m using the emacs set up from https://www.braveclojure.com , I wanted to add evil mode to it, how would I go about that?

rakyi19:07:33

@joshua.d.horwitz I don’t know about only adding evil, but https://github.com/syl20bnr/spacemacs/ is pretty good for clojure and easy to setup

noisesmith19:07:23

evil mode ships with emacs, you can just turn it on whenever you like with M-x evil-mode or iirc (evil-mode 1) in your init

zlrth19:07:18

also, is matching guaranteed to be top-to-bottom? I’m relying on:

(let [x [1 1 2]]
              (match [x]
               [[_ _ 2]] :a0
               [[1 1 2]] :a1
               [[1 2 3]] :a2
               :else :a3))
to return :a0 (which it does)

zlrth19:07:10

(I mostly solved my previous set-of-matches problem by wrapping it in a let and doing (contains apparel-set apparel)

dpsutton20:07:39

Yes. Underneath it can reorder column matching but not row matching.

zlrth20:07:02

ah ok. that makes sense

dpsutton20:07:30

Easy way to remember is that it's common to put a wildcard matches at the end (I think the macro does this automatically too. Been a while) and if it could reorder rows it would possibly match the most general case

johnj21:07:28

@noisesmith evil mode doesn't ship with emacs, it has other built-in vi modes though