Fork me on GitHub
#beginners
<
2019-02-23
>
chase-lambert00:02:08

so I'm studying a bit on atoms and I see what deref does but what exactly is happening? What does dereferencing mean? I assume it means the atom is a reference? A reference to a mutable data structure called an atom?

dpsutton00:02:41

the source of it is very straight forward. you can read it in java and perhaps even easier to read the cljs version

dpsutton01:02:04

(deftype Atom [state meta validator watches]
  ...
  IDeref
  (-deref [_] state)
in cljs and in java:
final AtomicReference state;
public Object deref(){
    return state.get();
}

hiredman01:02:21

it is tricky to discuss precisely because in clojure references mean these constructs for controlled mutation, but the jvm has references and they immutable

hiredman01:02:47

so you have to bridge this chasm of conflicting terminology

hiredman01:02:18

an atom is an object with a mutable field that can be mutated in an atomic way

hiredman01:02:25

deref gets the value of the field

chase-lambert01:02:28

thank you. I'll check these out. with my own searching I am at the http://clojure.org/reference (coincidental name) page and it's going over a higher level discussion of what they are and the terminology.

chase-lambert01:02:58

ahh, that was what I was starting to understand. thank you. So when you say object is that in a "object oriented" programming way? Sometimes I wonder what I'm missing out on by mostly starting in the clojure/functional programming world without learning the other stuff. It all seems to reference other languages.

hiredman01:02:25

like, it could also be an array of size 1, as long as you can do an atomic compare and set on the first element in the array

chase-lambert01:02:42

"mutated in an atomic way" "atomic compare" but what does "atomic" mean in the programming world?

hiredman01:02:42

I guess I meant "mutated in an atomic way" as synonymous with compare and set

hiredman01:02:07

compare and set is a very useful primitive for multithreaded programs

hiredman01:02:54

there are different forms of it (as cpu instructures which the jvm stuff jits to,)

hiredman01:02:39

and it is something like "read this value form this location in memory M, compare it against this other value A and if it matches, write this other value B to this location in memory M"

hiredman01:02:27

and it does that atomically, meaning no other executing threads/cpus can see the intermediate values or execute in the middle of that sequence of instructions

chase-lambert01:02:33

I think that was a part of it I was missing. It's because I couldn't explain my confusion. I was seeing why we would use atoms and how they were used (on a beginner level of course) but I would like to understand the entire underlying concept of what "atomic" meant.

hiredman01:02:37

https://en.wikipedia.org/wiki/Atomic_operation (which redirects to linearizability) is where the atom in clojure comes from, which is entirely different then the atom in most other lisps

chase-lambert01:02:30

good stuff. so is this one way to keep things "thread safe"? I see that pop up when people discuss concurrency. Basically a way so you know multiple...things? aren't changing the value from underneath you.

hiredman01:02:16

yes, it is a mechanism for sharing changing information between threads in a controlled way

chase-lambert01:02:55

thanks for the chat and clarifications!

john03:02:01

Note though that in cljs it's just a set!. The swap/deref protocol is a great way to organize transformation functionally, but in cljs multi threaded concurrency safety didn't motivate the implementation details.

john03:02:49

In JS, "isolates" have run to completion semantics, so effectively the whole environment is atomic.

db034904:02:16

Hello, I'm in the process of learning clojure. I've been using Joy of Clojure as learning material and http://Exercism.io for practice. I'm at the point now where I'm learning macros, but I've a hard time to finding practice problems for macros. Can anyone point me in the right place?

alexmiller04:02:23

Pick stuff out of core and rewrite it - and, or, when, dotimes, etc

alex-dixon05:02:02

(ns a)

(defprotocol Window
  (height [window])
  (width [window]))

(def window
  (reify Window
    (width [_] (.-innerWidth js/window))
    (height [_] (.-innerHeight js/window))))

((juxt width height) window)
Is there a way to get width and height from window when window is required in another namespace?

alex-dixon05:02:05

Oh…weird. Looks like (a/width a/window) … ? Not sure how that works but looks like it does

hiredman05:02:34

that is correct

hiredman05:02:53

a protocol is a collection of functions defined in a namespace

hiredman05:02:42

so just like if you did a (defn foo [x] ...) in namespace a, you would refer to it in other namespaces like a/foo, the functions in the protocol are the same

ryan.russell01112:02:15

can someone point me to some references or project examples for creating a full stack Clojure(script) application? I've been looking things up and can't find anything that isn't super outdated, or provides the information I'm looking for 😕

ryan.russell01112:02:15

can someone point me to some references or project examples for creating a full stack Clojure(script) application? I've been looking things up and can't find anything that isn't super outdated, or provides the information I'm looking for 😕

henrik15:02:54

The community has been sharing this a lot towards the end of this week. I haven't tried it myself, but it looks interesting: https://github.com/oakes/full-stack-clj-example

henrik15:02:57

It uses the comparatively recent deps.edn for dependencies, and pulls in the more traditional Leiningen for packaging and distribution. For #clojurescript development, it uses the excellent #figwheel, which is certainly best practice as of right now (the other equally viable path being to use #shadow-cljs)

ryan.russell01117:02:34

Thanks! I'll definitely check that out!

lucio12:02:22

@ryan.russell011 Edge ... https://github.com/juxt/edge read the docs on how to start your own project.. and look at the tutorial.vent or phonebook folders in edge to see some sample projects ;)

ryan.russell01113:02:43

Thanks.. I'll check it out.

victorbjelkholm42915:02:16

@ryan.russell011 https://github.com/ipfs-shipyard/cube/ is a fullstack clojure + clojurescript application. See the instructions over at https://github.com/ipfs-shipyard/cube/blob/master/docs/contributing.md#quickstart for how to run it

nvm-registrations16:02:42

Hello, is this the right place to ask questions about clj libs? I have a question about compojure

chase-lambert16:02:18

yup! No need to ask to ask. The friendly folks here will guide you to a more appropriate channel if relevant.

nicholas.jaunsen16:02:43

How does one import a spec/def which is defined in another file? I have a spec/def ::networkgraph which I want to import but I don't know how. Doing [backend.netjson.networkgraph-test :refer [networkgraph]] and then using it as ::networkgraph or :networkgraph doesn't work.

nvm-registrations16:02:42

cool! So, I'm reading a book on web dev in clojure. It uses wrap-routes the following way:

(def app-routes
  (routes
    (wrap-routes #'home-routes middleware/wrap-csrf)
    (route/not-found <some 404 response here>))
routes is from compojure.core and home-routes is just a collection of some routes defined with defroutes. The text explains usage of wrap-routes the following way: > The wrap-routes macro is used to ensure that the middleware is applied after the route is resolved, allowing us to restrict it to the home-routes. Had we wrapped these routes directly with (middleware/wrap-csrf home-routes) then the wrap-csrf would end up being applied to any routes defined below home-routes as it's now part of the common middleware chain. I thought about the "common middleware chain" phrase a lot, and couldn't get it at all and I couldn't find any documentation or example on the Internet that would explain this. The implementation of wrap-routes was somewhat hard for me to follow. Finally, I made my own sandbox example and tried using wrap-routes vs direct calling middleware. What I can see, is that compojure has additional behavior to ring handlers: when none of the routes match the requested URI, the handler returns nil. If we wrap this handler with the direct call to some middleware, that middleware will be called on nil and can theoretically return non-nil value, and thus prevent trying other handlers that go after it. Could there be a mistake in the book, or is "common middleware chain" indeed a thing? Or maybe I'm just lost in terminology and the book basically says the same thing I found experimentally? Thank you

chase-lambert20:02:35

i should've warned ya that the weekend traffic can be a little light on here. hopefully someone can help ya out

eggsyntax21:02:32

Hi @, welcome! I’m out of practice with ring/compojure, but I just wanted to point you to their respective wikis in case you hadn’t seen them, and to suggest that you might want to repost this in the #ring channel. https://github.com/ring-clojure/ring/wiki https://github.com/weavejester/compojure/wiki Good luck!

nicholas.jaunsen17:02:09

Not sure if this is the correct way to use specs. Is there another way to use specs which are registered in a different file?

nicholas.jaunsen17:02:12

nvm I figured out how registration works

nicholas.jaunsen17:02:27

So I have this kind of a folder structure and the spec part is registered as a test root, but for some reason no namespaces inside of spec are recognised.

nicholas.jaunsen17:02:27

Weirdly enough Cursive is able to autocomplete correctly for namespaces inside of the spec directory.

nicholas.jaunsen18:02:43

The solution was to add the spec dir to :test-paths in the project.clj file

lvbarbosa23:02:42

Is there a way to test recursive functions with midje and use provided on the function being tested?

lvbarbosa23:02:50

something like:

(j/config->job {:type :composite, :children [.jc1. .jc2.]}) => (j/make-composite-job .j1. .j2.)
      (provided
        (j/config->job .jc1.) => .j1. :times 1
        (j/config->job .jc2.) => .j2. :times 1)

lvbarbosa23:02:00

I am getting the failure message: FAIL at (job_test.clj:74) You never said #'config->job would be called with these arguments: [{:type :composite, :children [.jc1. .jc2.]}]