Fork me on GitHub
#beginners
<
2017-10-25
>
drewverlee00:10:53

are their any problems with referring ... cross referring namespaces?

(ns foo (:require [bar]))
(ns bar (:require [foo]))
I would think so, but i just tried it at seems to work.

noisesmith00:10:48

it will work if the other ns already exists in your process

noisesmith00:10:03

circular deps break when starting from scratch though

drewverlee00:10:28

so its better to just think of a different way?

noisesmith00:10:39

the answer is usually a third ns that uses both

noisesmith00:10:48

or a third ns that both use

noisesmith00:10:04

for things near the "edges" of my system (things other code outside my codebase interact with) it's often worth it to break things up into a protocol and something that implements the protocol - the code defining the protocol has no dependencies and everyone can access it, and other namespaces can implement its functions

noisesmith00:10:35

that way everybody can call code from everybody else, as long as the functions called are protocol functions and the implementing things are passed in at runtime

drewverlee01:10:54

Thats interesting, ill have to bookmark that thought and think about it for a while. I have been shying away from protocols. I think i understand the usefulness, i just assumed it was mainly about the polymorphism.

noisesmith01:10:32

it is mainly about polymorphism, but it can be a useful kind of indirection as well

noisesmith01:10:37

but it's not always appropriate to formalize things like that, functions and hash-maps get you pretty far too, it depends on what you are implementing and how it's meant to be used

drewverlee01:10:56

i think i understand, for my immediate problem i just reconciled that even though the vars were the same values, they weren't really the same var. So i can duplicate var across the two namespaces, as its actual more clear that way (they dont need to be kept in sync).

noisesmith01:10:34

this is why protocols help, since the functionality belongs to an object, not a namespace, and each object can interact with functionality provided by the other if you line up the argument passing right

drewverlee01:10:04

If the shared concept was a datastructure though, would this be relevant? (def person "jeff") in namespace foo and in bar? I think i might need to see a toy example to be sure i understand you correctly.

noisesmith01:10:49

look at how clojure implements datastructures - it's protocol first, all the code on datastructures targets a protocol not a specific class

noisesmith01:10:08

but wait, "jeff" isn't a datastructure, it's a string

noisesmith01:10:01

the idea is that instead of referring to globals in other namespaces, you use keywords to access it on a record if it's data, and protocol methods to invoke it if it's code

noisesmith01:10:36

when you aren't pointing at a global any more, the circularity problems disappear

drewverlee01:10:48

Your right "jeff" is just a string, i suppose i was trying to express that my global is data that wasn't a function. i must have a misunderstanding. How does it change circulatory problems if i refer to a map vs a record? I thought records were just maps that were more faster to do runtime dispatch on with procols (vs multimethods). Are records not namespaced in the same way?

noisesmith02:10:45

a map doesn't belong to some global storage, so it's easy to make two namespaces share functionality via a map

devn04:10:31

@drewverlee code organization has always been a bit of a hurdle IMO. I think Zach Tellman’s book Elements of Clojure is worth a read, as is Practical Clojure.

vinai09:10:42

Is there an idiomatic non-lazy version of a single level flatmap that can be used instead of (apply contact (map ...))?

vinai09:10:07

into only has 2 arities.

rauh09:10:42

@vinai (into [] cat [coll0 coll1 coll2])

vinai09:10:15

Thanks @rauh... need to digest that one a moment 🙂

vinai09:10:48

Oh, cat is cool. Never saw it until now!

orestis12:10:24

Hello! Do you have suggestions for open-source projects that showcase the strengths of combining Clojure on the server with Clojurescript on the browser? Simple or complex, I'm just curious to see how such a project would look like.

lepistane14:10:45

is there actively developed clj oauth library ? from Web Dev with Clj i got https://github.com/mattrepl/clj-oauth but last commit was in 2016 is that still good for production ?

seancorfield15:10:06

@lepistane A lot of Clojure libraries are small but become stable quickly and often need no further maintenance. Last commit isn't always a useful measure. See if there are outstanding PRs or issues with no follow-up from the maintainer.

lepistane16:10:06

makes sense i will pay more attention on that

wpcarro17:10:53

Hi. I’ve done most of my variable assignments with (let ...) and (def ...). If I declare a variable with (declare x), how can I later assign a value to x?

sundarj17:10:18

declare does a def behind the scenes anyway

sundarj17:10:47

(macroexpand '(declare a b c))
(do (def a) (def b) (def c))

manutter5117:10:40

@wpcarro declare is mostly useful for defining functions, where fn A calls fn B and B calls A. Use (declare B) so the compiler won’t complain about undefined vars, then define fn A using B, then define B with defn just like you normally would.

wpcarro17:10:50

@manutter51 ah the motivation behind that makes sense since there’s no hoisting etc

lepistane17:10:55

whole point of functional programming is to avoid variable assignment @wpcarro read https://mitpress.mit.edu/sicp/full-text/book/book.html get fully get what i am talking about having said that i haven't used declare so i am unable to help you there specifically. hope you are using assignment intelligently good lcuky

wpcarro17:10:02

thanks @sundarj did not know that

wpcarro17:10:44

@lepistane I’m familiar with the impetus behind FP… unfortunately I’m porting a JavaScript example to ClojureScript ………. it’s full of evil

ajs20:10:32

usually, when porting something from JS to Cljs, it should not be a literal port (if you have the time) and rather it should be re-thought in a functional context. A literal port would not be very idiomatic Cljs most of the time.

lepistane08:10:41

i agree with @U5YHNV0EA on this i maybe you should use atoms instead of declarations good luck

wpcarro17:10:23

I need to share a variable b/w functions A and B when function A assigns a value to the variable

wpcarro17:10:13

I assume that (declare x) as a peer to (defn a [] (def x 10)) will allow (defn b [] x) to return 10

wpcarro17:10:37

I supposed I should just cider-scratch buffer to verify

sundarj17:10:38

def creates a top-level var no matter where it is

wpcarro17:10:03

@sundarj is there anyway to make a function-local variable without (let ...)?

sundarj17:10:48

let is the way to do that

dpsutton17:10:51

can you explain what issue you are working around. when fighting assignment and such like this normally if you change your approach to the problem, this manufactured problem goes away

wpcarro17:10:17

@dpsutton basically I need a function A to assign to a variable that function B can access later in execution

dpsutton17:10:05

so you want B to pass a value to A and A can decide to return that value or a different one upon consideration of other things

wpcarro17:10:44

@dpsutton not quite… a library will be calling A first then B second, so unfortunately I don’t have control over which arguments are passed in

sundarj17:10:52

(defn a [] (def x 10)) will create the top-level x var regardless of whether it has been declared beforehand

wpcarro17:10:11

@sundarj that seems closer to what I’m after

dpsutton17:10:47

and you are not in control of the library?

wpcarro17:10:01

@dpsutton unfortunately not

dpsutton17:10:25

i'm not sure i see how creation of a new var would help you, as presumably B is not looking for this new var?

sundarj17:10:11

(defn a [] (def x 10))                                   
#'boot.user/a

(defn b [] x)                                            
#'boot.user/b

(b)
#object[clojure.lang.Var$Unbound 0x246769c2 "Unbound: #'boot.user/x"]

(a)                                                      
#'boot.user/x
                                                  
(b)                                                      
10

wpcarro17:10:50

ah this is it exactly… thank you @sundarj

wpcarro17:10:34

strange that the (def ...) leaks out of its lexical scope… so be it!

sundarj17:10:09

def is only for creating top-level vars

sundarj17:10:28

it's not like JavaScript, where var is for both top-level and local variables

dpsutton17:10:30

ie, its lexical scope is the ns

wpcarro17:10:57

ah great … thanks for the help @sundarj and @dpsutton

sundarj17:10:41

any time 🙂

jlee6920:10:27

hi i'm completely new to clojure and am interested in doing some rapid prototyping for a project in this environment. Can anyone recommend a library or framework that provides off-the-shelf support for account creation/managment/user provisioning?

seancorfield20:10:03

@jlee69 Clojure tends to avoid frameworks and instead focuses on small, composable libraries -- so you're not likely to find anything off-the-shelf for that use case.

seancorfield20:10:41

If you're looking to jump start a small web application, a lot of people recommend Luminus (I haven't used it so I can't comment).

admay20:10:14

I can recommend Luminus. There is a well built and well documented leiningen template to help get you started as well as a very well documented approach to web apps. It’s a very good place to start!

jlee6920:10:34

@seancorfield @admay thanks for the responses, i'll check out luminus

admay21:10:03

No worries @jlee69! Good luck!

tdantas22:10:14

I really don’t know what is going on I’m trying to implement the reaload workflow of stuart sierra and I installed the reloaded.repl and once I try to refresh I’m getting the following error

#error {
 :cause "namespace 'okivia.app.routes' not found after loading '/okivia/app/routes'"

tdantas22:10:51

`
[{:type clojure.lang.Compiler$CompilerException
   :message "java.lang.Exception: namespace 'okivia.app.routes' not found after loading '/okivia/app/routes', compiling:(okivia/components/server.clj:1:1)"
   :at [clojure.core$throw_if invokeStatic "core.clj" 5656]}

tdantas22:10:22

when I run lein uberjar and after that java -jar okivia.jar it is working great

tdantas22:10:49

both refresh and refresh-all I’m getting the error above

noisesmith22:10:39

what if you run lein clean before starting your repl?

noisesmith22:10:52

uberjar can break refresh if you don’t clean

tdantas22:10:20

will try now

tdantas22:10:27

now, do you know why the uberjar break the refresh ?

noisesmith22:10:09

yes, if clojure finds a class file and a source file, it prefers that class file

noisesmith22:10:43

thus, your source file isn’t used, and the resulting skew (in particular if you have new source files that are loaded when you change them, plus old ones that are not)

tdantas22:10:47

supposing I — tab 1 * lein do clean, repl * (refresh) - work great — other tab lein uberjar — back to tab 1 * (refresh) why not use the pre-compiled uberjar class ?

noisesmith23:10:32

I wonder - that could have to do with what refresh is doing, it might explicitly use the source file if it knows it came from one

noisesmith23:10:40

eg. using load-file instead of require

ThadIsNOTFood23:10:21

if I want to change the state of a style is this correct? cljs (set! class.style.display "something")?

athomasoriginal23:10:48

Try something like

(set! (.. element -class -display) "something")

;; or 

(set! (.-display .-class element) "something")