Fork me on GitHub
#beginners
<
2017-10-20
>
ThadIsNOTFood02:10:44

hello wonderful people, I'm looking for direction on how best to use a set of popup for data presentation (not ads, this is an internal tool, clojure/clojurescript/om)

val_waeselynck14:10:42

@U7AHRRSS2 sure, what is it you don't know how to do?

ThadIsNOTFood17:10:57

@U06GS6P1N I just don't know where to start I think I am googling for the wrong terms.

val_waeselynck15:10:49

@U7AHRRSS2 it's difficult to help without knowing what you already know how to do. Do you already have an Om app to add this functionality to? Do you know web development (in CLJS)? Are you wondering how to layout a poput in terms of HTML / CSS?

val_waeselynck16:10:50

In case that's the last one, I would have a look at bootstrap modal: http://getbootstrap.com/docs/4.0/components/modal/

Javier Pérez15:10:28

Hi everyone! I was trying to convert some strings into numeric literals and got some unexpected behaviour. Can someone explain this?

(read-string "07")
=> 7
(read-string "08")
NumberFormatException Invalid number: 08  clojure.lang.LispReader.readNumber (LispReader.java:330)
(read-string "09")
NumberFormatException Invalid number: 09  clojure.lang.LispReader.readNumber (LispReader.java:330)
(read-string "10")
=> 10

noisesmith15:10:29

@javipeg try 010 - that might be a clue

Javier Pérez15:10:55

That one works too

noisesmith15:10:02

right, but look at what it returns

Javier Pérez15:10:49

(read-string "010")
=> 8

noisesmith15:10:06

it's octal - leading 0 tells it the number is base 8

noisesmith15:10:48

+user=> (read-string "36rclojureiscool")
59714396063025843189N

noisesmith15:10:04

that tells it to use base 36 😄 - pretty useless but funny

ThadIsNOTFood18:10:19

I'm still looking for assistance in getting a data popup sorted out. Basically, in om I need to have a button that launches a popup modal with close button with scroll that pretty prints a PersistentMap.

ThadIsNOTFood18:10:48

What I currently have but it isn't quite working

(dom/button #js{:onClick #(js/alert (with-out-str (cljs.pprint (-> data))))} "Model")

csm21:10:36

Possibly your lambda isn’t correct. Since it takes no arguments, it might be getting passed and argument, and the execution would fail.

csm21:10:24

Maybe (fn [_] (js/alert ...)) instead of #(js/alert ...)

ThadIsNOTFood21:10:16

I rebooted and it started working

ThadIsNOTFood21:10:29

(dom/button #js{:onClick #(js/alert (with-out-str (pprint/pprint (-> data))))} "Model") Will be a quick fix until I can get a more permanent modal up

noisesmith18:10:49

isn't cljs.pprint a namespace? do you mean cljs.pprint/pprint ?

noisesmith18:10:12

or, really, you should require cljs.pprint and give it a shorter name in any ns that uses it

ThadIsNOTFood18:10:16

okay changed the call to pprint/pprint ...

ThadIsNOTFood18:10:42

but it still isn't launching the alert. But I'm not even sure that this is the correct way to do it as the PersistentMap is quite large.

Felipe Oliveira19:10:57

I'm a bit stuck here. I need to take a default value a sequence of keys and return a map with the default value set to each key.

Felipe Oliveira19:10:12

*a default value and a sequence of keys

noisesmith19:10:59

changing the value if the key is already there, or only updating with thedefault if not present?

Felipe Oliveira19:10:13

only updating with the default

noisesmith19:10:26

(merge defaults m)

noisesmith19:10:43

where defaults is a map from key to default value

noisesmith19:10:17

oh wait maybe I misunderstood

dpsutton19:10:30

you want the defaults to clobber?

noisesmith19:10:30

(zipmap keylist (repeat default))

Felipe Oliveira19:10:02

The output I need is {:a 1 :b 1 :c 1}. I must pass it 1 and [:a :b :c].

dpsutton19:10:04

anatpaatra, can you write out a small example of input and output and what the defaults are?

Felipe Oliveira19:10:36

oh damn, wait haah

dpsutton19:10:43

so you need to make a map out of a vector of keys and a single value, where each key in the vector has the single value you give it?

noisesmith19:10:05

clojurebot takes a while to wake up, haha

Felipe Oliveira19:10:37

@dpsutton a map out of a sequence of keys and a single value

dpsutton19:10:50

his second example is what you are looking for

noisesmith19:10:52

yeah, zipmap / repeat is the ticket there

dpsutton19:10:15

the great news is that you don't have to even write a function

tdantas19:10:28

hey @noisesmith, past few days you helped me a lot with the tip of using component to startup my system and stateful resources. one thing that I’m struggling to accomplish is that sentence > the idea is most of your functions stay pure, based only on arguments … how usually you accomplish that ? for instance, I have one endpoint ( using your idea of middleware to inject the database and other components I need ) that will validate against database and call one external service ( aws cognito ) . how you divide/organize your function to keep most pure as possible ?

Lucas Barbosa20:10:17

@oliv I’ve been trying to answer that question for the past couple of weeks

Lucas Barbosa20:10:31

I am reading SICP right now, to get a better understanding of functional design

Lucas Barbosa20:10:59

But I am still unsure of how to structure a large application

Lucas Barbosa20:10:23

in order to separate pure functions from dirty outside interactions

Lucas Barbosa20:10:12

btw, SICP is freaking awesome. I regret not reading it before! 😬

noisesmith20:10:58

@oliv the big picture answer is that the component/start function runs all your initializers (connecting to dbs, opening ports, opening files, all that) and the function that does that is the impure one - it takes a map with other components plus config and returns a "started component"

noisesmith20:10:28

the other components, plus your main app code, use the hash-map of started components returned by the component/start call to do all the things that need those resources

noisesmith20:10:48

of course you need pure and impure elements in real code - the trick is to make sure that you aren't pretending something is pure that leaks impurity underneath - the component architecture helps you do that by explicitly segregating startup from functionality

tdantas20:10:56

yeah, I see ! my “service” layer is a mixed of pure + impure ( database + service calls … )

tdantas20:10:09

feeling that I’m doing OO but with a different syntax

tbaldridge20:10:18

@oliv right, it's less about purity at that point, and more about making sure all the inputs to your function are given via arguments. That also makes it easier to test, want a temp DB? Just pass in a different arg.

tdantas20:10:08

yeah @tbaldridge exactly . my compromise right now is to receive everything that I need from arguments ( using component help me a lot )

noisesmith20:10:24

want a hash-map in memory instead of a document store when testing? if you wrote your component right, you can do that by providing a different arg on system startup

noisesmith20:10:40

yeah, sounds like you are doing it right so far then

tdantas20:10:15

so my functions ending with (defn whatever [hash-components args1 arg 2 .. ] )

tbaldridge20:10:27

Make sure though that each function takes only the components it needs. If you hand everything to every function there's a temptation to introduce tight coupling where everything needs everything in order to do anything.

tdantas20:10:10

so, my function should be (defn whatever [ db congito-client arg1 arg2 ] )

tdantas20:10:57

or I could destructuring (defn whatever [ {:keys [db cognito] } arg1 arg2 ])

noisesmith20:10:05

you don't have to split out the parts of the component, just write the components so you don't pass in things it doesn't need

noisesmith20:10:41

(and write the functions integrating with the components accordingly of course)

noisesmith20:10:50

yeah - the tight coupling around the component can be a problem for sure - it seems like someone is always trying to grab the global component reference and use that instead of using what's passed in, or write things that expect every single component to be available and visible

tbaldridge20:10:19

Component helps with this though

tbaldridge20:10:49

the system has all the components, but under each component's entry are the components it needs. so it's as simple as not passing the system to each function, but the component

tdantas20:10:04

yeah, better receive as arguments the components than use the system inside the function

Lucas Barbosa20:10:55

Is a function that receives another function as an argument and invokes it considered pure if the function given to it is impure?

Lucas Barbosa20:10:42

for instance: `

Lucas Barbosa20:10:07

(defn foo
  [bar]
  (bar))

Lucas Barbosa20:10:25

if bar can be impure, is foo pure?

noisesmith20:10:17

@lvbarbosa for the purpose I care about foo is pure - I can test it without mocking what bar does or creating an environment where it's safe to run bar in a test

noisesmith20:10:23

I can just provide a stub

noisesmith20:10:39

if foo isn't pure, map isn't pure, filter isn't pure, etc. - which most of us would find an odd definition of purity

Lucas Barbosa20:10:40

So I am not spreading impureness throughout my system if I start up some components (e.g. connection pools) and pass them around?

Lucas Barbosa20:10:03

hidden in functions or other abstractions

noisesmith20:10:12

it's containing impurity, because the other choice is to write code that directly accesses the impure capabilities via global references

noisesmith20:10:53

I wish "impurity" had a different name, because my desire for it as a software developer isn't about some sort of puritanical rejection of side effects, it is that if I contain impure things and use them as parameterizations of my code rather than building blocks, I can easily test and reason about the logic

tdantas20:10:56

so, the rule of thumbs is: avoid global references, always only use what you receive as arguments, right ?

noisesmith20:10:38

right - for things with side effects at least

mseddon20:10:47

constant global references are safe

noisesmith20:10:48

if we did that with everything our code would get very silly

noisesmith20:10:28

and in a good clojure codebase almost everything should be constant (modulo repl mechanics)

noisesmith20:10:49

the rest can be handled by your state management / initialization setup hopefully

mseddon21:10:59

i wonder, are dynamic vars considered bad in clojure, since technically they break referential transparency?

mseddon21:10:58

they seem used exactly how you would in common lisp, which is incredibly useful, yet it's clearly against the hard-line haskell position

sundarj21:10:14

nothing is ever outright bad, it's a matter of using features only when they are the best alternative and/or make sense. pragmatism in other words

sundarj21:10:03

referential transparency is a very good property to be strived for, but not at any cost

mseddon21:10:04

That's good news. I've found a few dynamic vars in libraries exactly where I wanted them too, which has been really refreshing in a JVM setting 🙂

sundarj21:10:11

good to hear!

mseddon21:10:46

[insert 'acceptable lisp' comment here]

shaun-mahood22:10:59

Are there any easy ways to consume free-floating jar files from Leiningen?

rcustodio22:10:14

hi, is it normal the clojure community use lowercase headers for http server?

seancorfield23:10:53

From RFC 2616 - "Hypertext Transfer Protocol -- HTTP/1.1", Section 4.2, "Message Headers": > Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive.

seancorfield23:10:55

I thought that standard Ring middleware for headers converted them to Sentence-Case before returning them, but I may be wrong that is not the case. I know that the middleware converts them all to lowercase to make them, essentially, case insensitive (and it specifically uses .equalsIgnoreCase to ensure case insensitivity).

seancorfield23:10:22

^ @rcustodio So, yes, it's normal to use lowercase -- because the Ring Spec says headers should be downcased prior to passing the Ring Request to a handler -- and they are not case sensitive so it doesn't matter whether you use lower-case or Sentence-Case.

mseddon23:10:54

I wonder why ring needs to lower case.

mseddon23:10:34

I suppose to merge in the multiple header case