Fork me on GitHub
#beginners
<
2017-09-10
>
mfm00:09:15

i’m having trouble getting oauth2 to work in a luminus app. when I enter:

(clj-http.client/post  ""
           {:accept :json
            :as     :json
            :form-params {:grant_type    "authorization_code"
                     ;;     :code          (get-in request [:query-params "code"])
                          :redirect_uri      "/oauth2/twitter/callback"
                          :client_id             "uFRreriTqef12qT1kwIQsz0as"
                          :client_secret     "a1VS3EnuXpXlNmUME0HEuqtvt7cdQWGEKfIp1gozt57aje6iHx"}})
in the repl, i get a warning about an invalid “expires” attribute:
Sep 09, 2017 11:59:30 PM org.apache.http.client.protocol.ResponseProcessCookies processCookies
WARNING: Invalid cookie header: "set-cookie: personalization_id="v1_vCZhEFIjziUVMdDtMGBTdQ=="; Expires=Mon, 09 Sep 2019 23:59:30 UTC; Path=/; Domain=.". Invalid 'expires' attribute: Mon, 09 Sep 2019 23:59:30 UTC
Sep 09, 2017 11:59:30 PM org.apache.http.client.protocol.ResponseProcessCookies processCookies
WARNING: Invalid cookie header: "set-cookie: guest_id=v1%3A150500157038061890; Expires=Mon, 09 Sep 2019 23:59:30 UTC; Path=/; Domain=.". Invalid 'expires' attribute: Mon, 09 Sep 2019 23:59:30 UTC

ExceptionInfo clj-http: status 401  slingshot.support/stack-trace (support.clj:201)
i’m not sure how to proceed. my goal is just to get the http POST working, but i’ve never done this before, so I’m at a loss as to how to give it the correct attributes.

noisesmith00:09:32

the cookie warnings are caused by the other end

noisesmith00:09:36

the error is a 401

mfm00:09:10

indeed. but i’m sure i’m doing one or more things wrong; i trust twitter’s api more than i trust myself.

noisesmith00:09:12

it could be that your form params aren't being translated to the precise keys the other end needs

noisesmith00:09:50

I don't trust auto-conversion of eg. :client-id to "ClientId" or is it supposed to be "clientId"

noisesmith00:09:02

or "Client-ID"

mfm00:09:06

interesting

noisesmith00:09:08

all of those are valid, why use keywords?

noisesmith00:09:19

use the actual string your endpoint wants

tagore00:09:21

The point, I think, is that there's an inherent contradiction in what we do, IMHO.

tagore00:09:01

We write programs entirely because we want them to cause side-effects.

tagore00:09:53

But we hate side-effects.

tagore00:09:43

So much of what we do as programmers is reconcile those two facts.

noisesmith00:09:03

@mfm my app uses clj-oauth 1.5.5 to get twitter oauth, you could check what their code looks like (or justuse that lib)

rcustodio00:09:39

Companies doesn't exist without side effects

mfm00:09:54

which app is this?

tagore00:09:17

It depends on how you look at it, I suppose, but life is mutable from my point of view. Things change.

noisesmith00:09:47

@mfm it's a closed source Saas that uses twitter heavily

tagore00:09:18

You could argue that the state of the world is a function of time, and immutable....

mfm00:09:21

oh thanks. i parsed “you could check their code” as “you could check my app’s code”

tagore00:09:36

That's getting deeper than I want to though.

mfm00:09:52

dumb question: i have to choose either oauth or oauth2? most people talk about “oauth”, and i can’t tell if they’re talking about oauth-and-its-relatives, or exclusively oauth.

noisesmith00:09:57

@mfm but really if you know what a successful request should look like, precisely (and knowing twitter they show you that usually) just using the actual string in the request data instead of a keyword reduces a bunch of silly problems in my experience

noisesmith00:09:07

don't use keywords for aesthetic reasons

noisesmith00:09:22

and values in a request aren't symbolic constants and aren't there primarily for your code to look up

mfm00:09:55

that makes sense.

tagore00:09:07

But, because state is a dangerous animal, an animal that has bitten some of us in the past, we want to lock it in a box.

tagore00:09:52

And we want to feed it (i.e. change it) in very controlled ways.

rcustodio00:09:35

A friend who uses erlang always give me hints, and he always said... you must isolate the state... always isolate things on their on context with their own states, isolate all

tagore00:09:34

Well, when you start to distribute state...

tagore00:09:09

there are no perfect answers

tagore00:09:22

there are only compromises

rcustodio00:09:00

That will depend the style the company do, or your own personal style

tagore00:09:41

Well, which compromise you choose will depend on that, I suppose.

rcustodio00:09:52

I'm learning isolating things, but that doesn't mean it's the right one or the best one

tagore00:09:02

You can either wait, or you can risk being wrong.

rcustodio00:09:36

Yes.. I'm new at this FP world, clojure world, and I'm really enjoying it.. the country where I live I think it's still not that strong.. but.. i like it

mjcleary00:09:45

Same here @rcustodio

rcustodio00:09:17

I'm from Brazil... and you guys? (Dunno if this is the right channel for that)

rcustodio00:09:12

Really... I though there was the strongest...

mjcleary00:09:34

I was agreeing more with the first part of your statement, sorry

tagore00:09:22

Well- don't take me too seriouosly..

tagore00:09:44

I am perhaps overly concerned with correctness,

tagore00:09:17

Especially when it comes to time.

rcustodio00:09:42

We've came to this chat to learn... so don't worry..

rcustodio00:09:17

It's really good to have someone who does the right thing (as possible) and teach the others to do it

tagore00:09:25

Much of what I do for a living is deal with time... it sounds simple, but in fact time is difficult.

mjcleary00:09:53

My question is, beyond the inherent benefits of FP and Clojure (immutability etc.), are there good selling points for integrating more Clojure calls into an existing Java codebase? I’m still a student, so I don’t have particular experience to better frame a situation, just looking for opportunities in a couple of upcoming projects

noisesmith00:09:40

fewer lines of code = fewer places for bugs to hide

noisesmith00:09:57

you can code clojure without a monster of an ide doing 3/4 of the work for you

noisesmith00:09:34

and of course, clojure and java can each call the other easily, so it is straightforward to build out clojure in existing java code

tagore00:09:38

Well, if you throw away the most significant benefits, then... no, right?

tagore00:09:02

Why would you discount them though?

mjcleary00:09:40

Ha, true I suppose. I figure trying to sell tangential benefits within Java might be easier than selling another paradigm to OOP mindets

tagore00:09:21

Well you can only do what you can do.

tagore00:09:42

I mainly write Javascript for a living.

noisesmith00:09:02

tangible benefits include better concurrency support than mainstream java approaches, and it's much easier to write ETL style data in / data out code in clojure with all the built in data transformation functions

tagore00:09:07

I'd love to write Clojurescript instead, but...

tagore00:09:24

Here's a question, a real question:

tagore00:09:59

Would the programmers you want to transition to Clojure be able to write Clojure?

hmaurer00:09:19

@tagore wouldn’t any programmer be able to write Clojure if they spent some time reading the doc?

mjcleary00:09:51

Not likely (probably won’t invest the time), it would probably just be me trying to get approval to implement my functionality with clojure and convince them to make the calls in their code

noisesmith00:09:33

I've definitely seen clojure delivered as part of a java app without getting approval to do a clojure project ("hey you didn't say we couldn't use clojure.jar to generate bytecode") but not every company would take that in good humor

seancorfield00:09:05

I've seen ColdFusion developers transition to Clojure -- and ClojureBridge takes beginners and gets them started on Clojure. So, yes, any programmer should be able to write Clojure. Whether you can convince any specific programmer to learn Clojure is a separate issue tho'...

tagore00:09:28

@hmaurer Kind of. But that doesn't mean any shop could just switch to Clojure painlessly.

tagore00:09:03

Look, I hate writing Javascript as much as the next guy, and I wish my shop were a Clojure shop.

tagore00:09:08

It would be almost criminally irresponsible of me to suggest that.

tagore00:09:59

Sure, clojurescript is a fundamentally better language than JS.

seancorfield00:09:21

This is a good talk for considering ways to introduce Clojure: https://www.youtube.com/watch?v=2WLgzCkhN2g

seancorfield00:09:01

I wrote this piece just over four years ago that talks about "enterprise" companies and how radical Clojure is: http://seancorfield.github.io/blog/2014/09/23/clojure-in-the-enterprise/ (note also the piece I link to by Eric Normand)

tagore00:09:23

But the reality is that we're taking a bridge looking toward a series A, and everyone I work with will be out of a job if we don't close both.

seancorfield00:09:21

(my blog post also links to Neal Ford's talk at the end, I just noticed)

tagore00:09:36

And that means we have to keep tricking, even if a lot of what we do is not correct.

tagore01:09:50

I'd love to make us a clojure shop, but... we have close to 200k lines of javascript.

tagore01:09:47

And 10 programmers who can (in some cases barely) write JS.

tagore01:09:13

There's the ideal, and then there's reality.

tagore01:09:36

And then there's the series A 😉

seancorfield01:09:33

(JavaScript mutterings and the "joys" of startup funding all belong in #off-topic -- not in #beginners -- this channel is supposed to be somewhere folks new to Clojure can ask beginner questions about Clojure and get specific answers)

seancorfield01:09:29

@mjcleary Wanted to check you saw the link to Neal Ford's talk and my blog post about introducing Clojure?

mjcleary01:09:38

Yes, thank you! I’m reading now. Video next

tagore01:09:30

@seancorfield OK, sorry- the thing is that many beginners do want to ask about their prospects, and the nature of the industry.

tagore01:09:26

I'm not sure what you mean by "JavaScript mutterings" I'll be sure to let all of the Javascript programmers I know that you feel that way though 😉.

tagore01:09:08

But I'll refrain from saying anything in this channel that isn't a matter of specicific answeres.

seancorfield01:09:08

And if folks ask about non-Clojure topics, feel free to direct them to a more appropriate channel...

seancorfield01:09:38

There's also a #jobs-discuss channel that's probably a good venue for general discussions about the Clojure job market, how to find a Clojure job, which companies are doing what with Clojure(Script) etc.

tagore01:09:36

Oh, I see 😉

stvnmllr202:09:32

Never can seem to find this. I'll write it down next time. What's the easiest way to write a big clojure data structure (map) to a file or db and read it back later.

noisesmith17:09:32

the way that is the least work is to use pr-str to create the text, and write that to the file, then use read-string got get it back there are a couple of problems with this, one level of improvement is to use clojure.edn/read-string or better yet make a Reader from the file and use clojure.edn/read, but the best option is actually to use cognitect/transit to do the write and read, this is better because it’s actually optimized for performance and it’s extensible without global config for any type you would like to put in a file, as long as you can make an appropriate reader and writer function. transit also uses a format that people can easily consume from other languages (it has bindings for quite a few popular languages already) https://github.com/cognitect/transit-clj

noisesmith17:09:47

I wrote a library to simplify dumping data to a file using transit, and then get it back. The main intended purpose is to simplify grabbing data from the repl and using it in unit tests or regression tests https://clojars.org/org.noisesmith/poirot

stvnmllr202:09:01

all of a sudden I found edn/read-string and it mentioned prn-str, so think i'm good.

noman02:09:16

hey guys are there any books or texts you'd recommend for learning how to "think in clojure", so to speak? does it just come over time from doing it or are there any texts that gave you an "a ha" moment, thanks

au-phiware03:09:38

I recommend any talk given by Rich Hickey!

au-phiware03:09:30

"Simple made Easy" if you haven't seen it yet (even if you have watch it again 😉) https://www.infoq.com/presentations/Simple-Made-Easy

au-phiware03:09:36

If you don't mind videos, I also recommend the entire "MIT 6.001 Structure and Interpretation" (1986) course, don't be fooled by the date, the concepts are extremely important! https://www.youtube.com/watch?v=2Op3QLzMgSY

noman05:09:00

cool, thanks friends. i've been watching a bunch of rich hickey talks and they have been helping. will check out the MIT one as well, thank you

evmin08:09:15

Good day.

stvnmllr212:09:18

@noman Good to have the concepts, but the only real way to think clojure (or maybe functional) is to do it. So if functional is new to you, just do stuff. http://4clojure.com was what helped change my brain.

noman17:09:53

Thanks I'll check out this site. I have some familiarity with thinking functionally from writing modern js and react code but clojure is on a whole other level.

lvbarbosa13:09:32

@au-phiware Thanks for the suggestions! I am almost finishing Rich’s talk and he just said something that made me intrigued. He says that we should not entangle components together, we should use queues instead and make them “independent islands”.

lvbarbosa13:09:21

How do I apply this in the context of a request/response architecture? I mean, the function that receives the request must call something in order to get that request processed and return a response

au-phiware13:09:45

It is a difficult question to answer without more specific circumstances... In one respect a server/client architecture has already created "independent islands", and is already asynchronous (client sends request and at some later time the server sends a response). However, I think you might be asking about the design of the server? Again it very much depends on the work that needs to be done in order to serve a request. But let's say there's some shared resource, say a database, and there is a contract or interface that you have defined for the shared resource. There may ways you could fulfill that contract, some of them will be asynchronous, some of those might involve callbacks and others might involve locks. To use queues or channels, your database might wait for requests to flow in on a channel, perform the work to fulfill the request and place the result on an outbound channel provided as part of the request, where the requester is ready and waiting for the result on that channel. I fear this is a rather long winded reply... Channels are a powerful concept, it allows you to shunt data around your app and focus on your data structures instead of your method signatures. HTH

lvbarbosa13:09:51

How do you make it async by pushing the request into a queue? This reminds me of Node.js and callbacks

lvbarbosa13:09:12

Does it make sense on such a small example?

lepistane14:09:34

i just listened https://www.youtube.com/watch?v=VNTQ-M_uSo8 he said he works on clojure, spec and contractor and consultant How can he manage all those things? it took me 40days of 5+ h/day to build my first app with reagent

hmaurer14:09:27

He probably figured out how to do reliable cloning

seancorfield17:09:20

Stu is one of Clojure's "elder statesmen" and he's a phenomenally smart dude -- superhuman! A lot of this is also the 10,000 hours thing. You get good at stuff by just doing it a lot and always be learning.

seancorfield17:09:35

I started doing open source work in the early 90's and it's something I always make time for so that I can keep learning beyond whatever work throws at me.

seancorfield17:09:20

And I make an effort to read technical books outside work and to learn a new language every year or two.

seancorfield17:09:45

Back in the day I would also save up and send myself to conferences or take training courses -- investing in myself. That's how I learned Clojure: a $200 workshop one Saturday. Totally worth the out of pocket expenses.

seancorfield17:09:08

A few years ago I sent myself to PyCon because I wanted to learn Python. One year I managed ten conferences (because several were local and fairly cheap).

seancorfield17:09:12

Mostly now I just go to Clojure/West and Clojure/conj -- totally worth it, if you can do it.

lepistane17:09:50

you are super human too you manage to chat you manage to help beginners you manage to contribute to opensource you manage to make money my god when i grow up i wanna be like you xD

seancorfield19:09:25

I'm flattered 🙂 To be honest, it's just about being mindful of how you spend your time: a few minutes on Slack here, a few minutes on the mailing list there, an hour reading a book instead of watching TV/playing games, carving out 30 minutes here and there in your work week to look at FOSS projects or read blogs or watch an online talk. Start early, make it a habit.

tbaldridge14:09:43

UI coding is a rather big time sink, one of the reasons I try to avoid it.

didibus07:09:16

Don't you maintain fn-fx 😛

lvbarbosa14:09:44

Still stretching out my questions/ignorance related to application design in Clojure… I am kind of lost at the moment. I want to understand some ways of organizing my code in order to make it as much decoupled as possible. I am not sure about unit testing anymore, is it really worth it in FP? Are the difficulties of async design paid by the benefits of using it? I have a lot of unanswered questions wandering in my brain right now 😱

didibus07:09:48

No one does async design by choice, try to always design synchronously. Only and only if you're problem absolutely requires async should you design that way.

didibus07:09:47

What you want is to keep functions pure and grouped in namespaces by loose association.

didibus07:09:23

You do want unit tests, where the unit is a single function. Those should be to avoid regression.

lvbarbosa13:09:46

Thank you, I really appreciate the response 😊 The only thing I’m still really lost is regarding how to design my functions

lvbarbosa13:09:04

I mean, how to make them testable if they invoke other functions by themselves

lvbarbosa13:09:18

for instance, if I have a ring handler that should extract the request data and pass it forward to another function

lvbarbosa13:09:54

this is how I am doing it right now : (defn handler [request] (otherFunction (extract-data request)))

lvbarbosa13:09:15

I can’t unit test this, because it is invoke something else, which will in turn invoke something else

lvbarbosa13:09:24

and eventually, the database will be invoked

lvbarbosa13:09:42

What I can test is the extract-data, for instance

lvbarbosa13:09:54

Does it make sense?

eggsyntax16:09:00

There are a range of opinions in the clj/s community about the value of unit testing. Some folks argue that REPL-driven development makes it less necessary; some feel that it's often better replaced by generative testing (which is made fairly easy by clojure.spec); and some feel that they're still very important. I'd say they have the highest value for functions that are most likely to end up with regression errors, ie functions that are likely to change. Tests that hit a DB are classically difficult to unit test. The most common solution, probably, is to replace the DB with a mock DB that'll always contain the same known values. Another useful approach is to separate out the DB function -- the part that's dependent on unknown state -- from the handling of the returned values, which can usually be written as a pure function, which is much easier to test. But that's definitely just my take on it -- there's no universal agreement in the community on the value of unit tests, and the best strategies for writing them.

lvbarbosa17:09:33

I see… well, I am looking into some ways of dependency injection in functional programming now

lvbarbosa17:09:03

Looks like it’s a good way of making my funcs more testable and pure

lvbarbosa17:09:11

instead of just chaining the invocation

lvbarbosa17:09:21

But as people said on the #beginners

lvbarbosa17:09:35

it will add overhead to the function calls, that seems inevitable

lvbarbosa17:09:03

Something that I really miss is a set of examples of good practices. I couldn’t find a more complex system in an open source platform that I could spend some time reading

noisesmith17:09:41

the most common way to do dependency injection for isolation of logic is to receive the dependency as an argument. You can either specify a protocol that the arg must satisfy (eg. the first arg to map must implent IFn), or document how it is used. Libraries like stuartsierra/component and weavejester/integrant have their own takes on how to isolate state management from dependency management, but each uses this technique of providing the dependency as an arg at runtime.

didibus23:09:15

Things are simpler in terms of program structure generally in FP. There's no issue having functions call other functions if they are all PURE. By pure, I mean none of them depends on inputs that are not provided through an argument. So never access a global Var, or query a DB, or read from a file. Try to do that for as much functions as you can.

didibus23:09:03

So if you have something that gets the name out of a file, you have it take an input-stream or a string, you don't have it read the file.

didibus23:09:59

Now, you won't be able to do this for 100% of the code, at some point, your code wants to interact with the outside world, user input, or remote state. What you want is to have your TOP level functions do these things.

didibus23:09:50

Ideally, you have a pattern like: main-orchestrating-fn calls a bunch of single I/O fn, like read-file, read-input, query-x-from-db, and passes the result of those to your pure functions. The I/O functions should not call other functions, they should just do the I/O and return. Your pure function are then free to call as many other pure function as needed, and nest deeply if necessary. Though in general, try to do more orchestration, and less nesting.

noisesmith23:09:05

also, you don't abstract IO generally - it's best to keep IO at the top level rather than hiding it under something else

noisesmith23:09:21

which is why you need the orchestrator, to call abstracted things and IO things, alternately

lvbarbosa14:09:21

This sounds like knowledge that will come with practice

lvbarbosa14:09:28

trial and error

lvbarbosa14:09:21

But is there any way to guide my learning? Any books/resources with more complex examples?

donaldball16:09:12

Lots of people seem to have gotten benefit from Clojure Applied, though I confess I have not had the pleasure of reading it yet.

donaldball16:09:44

My design thinking has been substantially informed by domain-driven design, which advocate bounded contexts. I tend to try to organize my larger applications around a set of core protocols, and look for opportunities to couple contexts using message queues instead of fn calls.

lvbarbosa13:09:10

I see… I’ll read the blue book again, with functional programming in mind. Thank you for the response!

ramblurr14:09:21

Is it possible to use react components (published in js) in re-frame? does anyone know of a code/app example in the wild?

tkjone18:09:02

does this interop macro have a name: .. ? I was looking at the docs and a few other resources and I have not been able to identify a name for it. https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/%2E%2E

alexmiller19:09:22

I don't think it has any special name

alexmiller19:09:34

Other than dot dot

tkjone19:09:08

Interesting. That must be fun trying to communicate it to others unfamiliar with the language 🙂 dot dot it is!

sudakatux21:09:14

im new to Clojure and this slack

hmaurer21:09:17

@sudakatux Welcome! 🙂

sudakatux21:09:46

Maybe someone can help me out, im looking to build a kind of middleweare which makes a request to an api, maps the request to something else and posts the data to Api2

sudakatux21:09:04

was looking into http-kit client

sudakatux21:09:20

This is BTW my second excersie app 😛

sudakatux21:09:39

Im struggleing with the simplest task

sudakatux21:09:05

So I require with the :as

sudakatux21:09:21

and i get namespace not found,

sudakatux21:09:28

(ns middleman.core
  (:require [org.httpkit.client :as http])
)

sudakatux21:09:58

and then in the repl if i do

@(http/get "")

CompilerException java.lang.RuntimeException: No such namespace:

sudakatux21:09:35

if i change that for @(org.httpkit.client/get "")

sudakatux21:09:37

why isnt http a smaller version of org.httpkit.client if im using the :as

hmaurer21:09:51

@sudakatux your ns code is correct. In the repl, are you within the namespace middleman.core?

sudakatux21:09:29

So im writing (use 'middleman.core :reload) to get it to reload after i make a change

sudakatux21:09:56

@hmaurer I think i got it

sudakatux21:09:21

so if i write it within a function on that file it does work

hmaurer21:09:53

I didn’t do much 😄 Glad you fixed it though

hmaurer21:09:12

To switch to a namespace, you should use in-ns (https://clojuredocs.org/clojure.core/in-ns) in the repl

hmaurer21:09:19

(if that’s something you want to do)

hmaurer21:09:32

use won’t let you access the librairies required in your namespace

hmaurer21:09:42

only the functions/variables

hmaurer21:09:56

(I am a beginner myself so don’t take my word as gospel, I might be wrong)

sudakatux21:09:51

thats what i wanted 🙂