This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-12-13
Channels
- # adventofcode (77)
- # beginners (132)
- # boot (11)
- # cider (40)
- # clara (10)
- # cljsjs (1)
- # cljsrn (4)
- # clojure (148)
- # clojure-android (1)
- # clojure-greece (5)
- # clojure-italy (5)
- # clojure-nl (7)
- # clojure-spec (57)
- # clojure-uk (9)
- # clojurescript (115)
- # core-matrix (1)
- # cursive (3)
- # data-science (1)
- # datomic (1)
- # duct (7)
- # emacs (20)
- # fulcro (29)
- # funcool (4)
- # graphql (31)
- # instaparse (15)
- # java (1)
- # jobs (6)
- # jobs-discuss (95)
- # leiningen (2)
- # off-topic (30)
- # om (4)
- # onyx (7)
- # pedestal (6)
- # quil (4)
- # re-frame (52)
- # reagent (59)
- # rum (1)
- # spacemacs (3)
- # specter (61)
- # test-check (3)
hi guys
I'm a bit lost with namespaced keywords
given I'm in a namespace foo.bar
, ::a
should evaluate to :foo.bar/a
what if I want to reference :foo.bar/a
from foo.baz
?
then you use :foo.bar/a or you can alias foo.bar to bar and use ::bar/a
alias is usually done via the :as key in require
oh, cool
what's the advantage of using ::bar/a
instead of :foo.bar/a
?
Clojure 1.9.0-RC2
(ins)user=> (ns foo.bar)
nil
(ins)foo.bar=> ::a
:foo.bar/a
(ins)foo.bar=> (ns foo.baz (:require [foo.bar :as b]))
nil
(ins)foo.baz=> ::b/a
:foo.bar/a
it’s more succinct
I see
thanks a mil @noisesmith
Hi guys, How mostly do you guys do your function tests? If there are moving parts, for example calling another function which query a database, making the function "impure", do you guys have some kind of convention to "inject" the parts into the parent function? For now I'm doing something like:
(defn register
([user create-fn]
(if-let [new-user (create-fn user)]
{:type :created :message (dissoc new-user :password)}
{:type :error :message {:error "failed to register user"}}))
([user]
(register user u/create)))
Is there a way to do it better, especially if the function gets more moving parts in it (the case of: if condition is A, do A', if condition is B do B') ?this is a normal way to do things in clojure code - especially if create-fn uses an initialized resource, in which case it’s conventional to pass in something that is created on initialization and knows that resource, rather than storing the resource globally in indeterminate state
if you need multiple operations on one logical entity, and also have it be something passed in, protocols match this pretty directly (and you can implement the protocol using reify or defrecord or deftype depending on your other needs)
but most people would say that this isn’t #beginners level material
Hi @noisesmith, sorry for the late reply. I've had some trouble trying to understand protocols usage in cases like this: 1. There's a namespace which cater solely for business logic and data transformation, at some point the functions in that namespace will need to call what I would call a repository function from another namespace to store the entity. 2. The logic namespace shouldn't care about the implementation of the storage itself, in most imperative language I would just use interface in the logic class, then inject a concrete class to it, if I want to change implementation later on I wouldn't have to change anything on the logic part, just have to inject something else. From what I understand, protocols rely on the type of the entity itself, which function implementation that will be invoked determined based on the type of the entity. How would it serve the above rules, especially the part of not having to change anything on the logic code?
The logic should only calling the functions defined in the protocol
It should not reference or access the actual type
The thing that implements the protocol should be passed in as an argument
Consider that you don't access methods that belong to clojure.lang.PersistentVector, instead you call a conj or get etc these use methods a vector implements from interfaces and protocols in clojure.core
Alright, I'll give it a try. Thank you for the pointer @noisesmith 😁
@hawari.rahman17 so (defn f [frobber] (foo.proto/frob frobber x)) then you can call it like (f (reify foo.proto.Frobber (frob [this x] ...)))
And in ns foo.proto (defprotocol Frobber (frob [this x]))
It usually only makes sense if you have at least two protocol methods you care about though (even if on two different protocols), otherwise why not just use a function
Thanks @noisesmith, guess I'll need to understand about protocol first 😁
So based on the function above, I inject a mocked function when testing, a function that immediately returns value just for the sake of testing the parent function.
So this maybe something that's asked quite a lot here, but I'll ask anyway. I find myself interested in clojure, I was interested in LISP some time back but never got the chance to use it. Now that I'm doing more web stuff (Doing django at my work atm), I started to read about clojurescript. It's been a couple of weeks and I see so many libraries and frameworks and comparisons between each other that I'm literally frozen by too many choices - it's debilitating. I only can do clojurescript in my spare time and that spare time is a bit hard to come by these days with all the other stuff in my life. To start with, I'm not a genius coder by any stretch of the imagination so I can't 'grok' a framework or a language in two afternoon. With all this, I go read abour reagent, re-frame, Fulcro, Keechma, Om next, etc. And there are so many blog posts detailing why one of these is better than the others. I started trying out re-frame once, tried Fulcro also. But for me this takes time. I am an intermediate level coder who'd like to just learn something useful and perhaps fun. I don't want to put a lot of effort into learning something (Doing a personal project with it say,) and learn later that that framework is abandoned. It seems there's so many stuff around at the moment that it's implausible to think that they all will survive for long. But if you look at other languages, they have either one or two well respected ways of doing something. So, what would be my safest bet? Any suggestions are welcome.
fwiw, I started out writing a simple Electron app using CLJS and reagent (because I couldn’t quite figure out the original Om). From there I moved up to re-frame, and found that it was easier to learn re-frame having first learned reagent, and also some things became easier in re-frame than they had been in reagent.
Then I did some (non-CLJS) tutorials on Falcor and Redux and found that these made it a lot easier to understand Om/Om Next.
So I’d say it’s not quite a case of “if I learn this one, my experience will be wasted.” There’s enough overlap between the React-based frameworks to make it worthwhile no matter which one you start with.
I used “Clojure for the Brave and True” for my main intro - I think it’s free to read online still. Now I’m making my way through “modern-cljs” to learn more about clojurescript. Just going to go with whatever he’s recommending!
@duminda - highly opinionated rite of passage in CLJS:
* reagent
(learn and understand basics of react
+ cljs
+ hiccup
)
* tooling: lein+figwheel
or boot+boot-reload
; Just stick with one template that runs out of the box for you.
* side-quest: have a look at garden
* re-frame
(learn one-way dataflow + how to structure apps)
* rum
(easily compare different ways of managing state at a component level; learn the pros/cons of each)
* om/next
(one approach to highly complex apps)
* fulcro
(one opinionated approach to build om/next apps)
At this point, you have gained the knowledge you need to make your own decisions based on project needs and you’ll know what interests you and where to dig deeper.
Thanks guys for the detailed responses. So I will just start with reagent as recommended. Hopefully I can move on to other stuff after that.
when I'm picking a tool, I usually go look at the options on https://www.clojure-toolbox.com/ and pick a project that seems well-established
@duminda having spent the last year playing with om.next and clojurescript, i'm currently evaluating rum and it's really good. i'm not sure what sort of web dev you're working on. my needs are: realtime server-> client and client -> server comms for which I use sente. beyond that, my current recommendation would be rum. i'm just getting started with datascript, which is like a clientside db that looks like datomic syntax. Check out this post and see if you're building something that would benefit from this model / approach. http://tonsky.me/blog/the-web-after-tomorrow/
@hawari.rahman17 i'm curious about this too. making fake inputs to test database grabs seems like a decent way to get about it.
Yup @sova, as of now it's decent enough to get by. But I still kinda have a feeling I'm missing out on something here. 😆
Hey all, I'm really confused about core.async
Can someone help me understand why this doesn't return "Hello World"?
@derpocious
A few problems:
On line 13, you're taken the "Hello Word" out of the channel and discarded it.
On line 15 you returned an empty channel instead of "Hello World".
go
also returns a channel so you must take from the channel returned by the go
block
Since Klipse runs on CLJS in the browser, you can't take from the channel synchronously. This will work in Klipse:
(def a-channel (chan 1))
(put! a-channel "Hello World")
(take! a-channel println)
Thanks.
But why is it (take! a-channel println) instead of (println (take! a-channel))
Hmm I thought <! was also async take a value off of a channel
<!
is only available in a go
block
thanks. I need I need to require source. Does it work in cljs?
what's the best way to find the import for cljs?
For example, take! just causes my code to break and googling "cljs take!" doesn't seem to give me the answer
There's no take!
function in http://cljs.github.io/api/
Looks like it's not implemented.
so trying to implement a nightly email job for a web app. would it be recommended to run it in a separate process from the web request it gets triggered by? if so, is there a simple way to do that. or need core-async
There are a lot of variables to consider when answering that question. Is your web service process currently a singleton? Likely to remain that way? Must your job be run by only one process? Do startup time or other operational considerations suggest adding other processes is a pita?
Yeah, there are. I'll probably have more than one running at some point so i can restart them without downtime. Only want one a night, as it sends daily tasks for each user. I can add other processes if needed. But yeah, started with lambda, but wasn't easy to get access to db and email service without another NAT router or something like that.
My current idea is to have lambda call the url (which is load balanced) so it runs once.
Oops. thanks @U04V4HWQ4. See above if you are still on today
lambda calling the url would be easy and effective if you’re satisfied with the security story. Alternately you could coordinate electing a leader, which would be nice potentially if your app could know when the job was finished successfully so you could potentially retry failures.
yeah, security is ok with https i think and a shared key. Hmm.. you mean knowing which web app would handle it? I'd know success by the result of the lambda function, but not sure what to do about it if it fails. Have to look more into lambda triggers i guess. Thanks for the input.
Assuming your request is processed synchronously and the response does not timeout 🙂
is it possible to rollback a transaction created inside a dosync
call on purpose and without having to throw an exception?
shouldn’t anything that rolls back a transaction throw an exception to the caller? otherwise I’d expect strange and very hard to find bugs
if throwing an exception to the caller is OK, but you don’t want to create one artificially you could call (io!)
maybe?
or make the ref something that is passed in explicitly, so you can create fresh ones explicitly for each test
that’s often a good pattern, making all mutable resources (refs would count as a mutable resource) be arguments rather than namespace level globals
a compromise is to accept an explicit resource arg, and default to the global
that way at least your tests can be sane
i'm doing the opposite of that, i have them defined as namespace level globals, then on my unit tests i'm binding them to another value
right, that’s the thing that causes problems and the thing I’m saying maybe not do
in particular, since the use case for refs is for things where performance concerns mean you want to reduce contention and coordinate acting on N items - that’s often a case where you want a collection of refs and that gets inconvenient with globals
i decided to do it like that because i'm using them in multimethods, it seemed to make more sense, but i'll see if i can work on a refactor
derpocious Hey all, I'm really confused about core.async Can someone help me understand why this doesn't return "Hello World"? http://app.klipse.tech/?cljs_in=(ns%20demo.core%0A%20%20(%3Arequire-macros%20%5Bcljs.core.async.macros%20%3Arefer%20%5Bgo%20go-loop%5D%5D)%0A%20%20(%3Arequire%20%5Bgoog.dom%20%3Aas%20dom%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bgoog.events%20%3Aas%20events%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bcljs.core.async%20%3Arefer%20%5Bput!%20chan%20%3C!%20%3E!%20timeout%20close!%5D%5D))%0A%0A(def%20a-channel%20(chan%201))%0A%0A(go%0A%0A(%3E!%20a-channel%20%22Hello%2C%20world!%22)%0A%0A(%3C!%20a-channel)%0A%20%20%0A%20%20a-channel)
hello, anyone knows why the clj executable doesn't return anything?
I've installed rlwrap already
I hoped in the tutorial to open the repl
I've used the bash installer
using linux mint latest
so it just silently exits?
@vinnyataide You need to install Leiningen: https://leiningen.org/#install
That's the easiest way, then you can run lein repl
.
I think I found the problem
I have no java
It's a brand new
@ghsgd2 that’s an alternative but the clj tool is totally different
It should check and warns doesnt it?
@vinnyataide haha that would do it
So that remains as a future feature haha
@vinnyataide yeah that would be worth a PR or jira ticket I bet
can I do it? or would I need to call someone?
you can make a PR or jira ticket - anyone can make a jira tiket, you need to sign up an online contributor agreement or they won’t look at a patch though
ok thanks
@vinnyataide either way you would start around here https://dev.clojure.org/jira/secure/QuickSearch.jspa
will do! just a heads up a default-jre install solved it
:thumbsup:
Hello everyone, recently I started with a book called web-development-clojure v2
The libraries it uses changed slightly, according to the book I need to connect to repl and run a query on the db
That is what I have:
user=> (use 'guestbook.db.core)
nil
user=> (get-
get-in get-messages get-method
get-proxy-class get-thread-bindings get-validator
user=> (get-messages)
IllegalArgumentException db-spec mount.core.DerefableState@61222e9e is missing a required parameter clojure.java.jdbc/get-connection (jdbc.clj:379)
My db.core:
(ns guestbook.db.core
(:require
[clj-time.jdbc]
[conman.core :as conman]
[mount.core :refer [defstate]]
[guestbook.config :refer [env]]))
(defstate ^:dynamic *db*
:start (conman/connect! {:jdbc-url (env :database-url)})
:stop (conman/disconnect! *db*))
(conman/bind-connection *db* "sql/queries.sql")
My queries:
-- :name save-message!
-- :doc creates a new message
INSERT INTO guestbook
(name, message, timestamp)
VALUES (:name, :message, :timestamp)
-- :name get-messages
-- :doc selects all availible messages
SELECT * from guestbook
I tried to reinstall the whole project 3 times already, but could figure out the problem. Could smbd pls point me to the right direction?@janis.urbis Does the book tell you which versions of the libraries to use? (in your project.clj
I expect)
If you change the versions from what's in the book, you will run into incompatibilities between the libraries.
@seancorfield no, it's just says use luminus
Thanks @chris!
I changed migration to what book requires
CREATE TABLE guestbook
(id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30),
message VARCHAR(200),
timestamp TIMESTAMP);
It is possible for me to return the value that was in the channel instead of just printing it?
@janis.urbis How did the book tell you to create the project?
The author @yogthos is on this Slack but not in #beginners -- I'll invite him in
@yogthos wondering if you can help @janis.urbis as he's trying to follow the guestbook example in your book?
@janis.urbis the error you’re seeing means that the database state hasn’t been started yet
mount uses namespace hierarchy to resolve the resource loading order, and if a namespace isn’t included anywhere, then the resources in that namespace won’t be loaded automatically
to load the resource by hand you just have to run (mount.core/start #'guestbook.db.core/*db*)
in the REPL
@janis.urbis try running (mount/start #'database)
in the repl and run the query again
(sometimes there's so much "magic" in these Leiningen templates that they're not the easiest way for beginners to learn Clojure!)
@admay @seancorfield thank you for the help too 🙂