This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-19
Channels
- # announcements (6)
- # aws (10)
- # beginners (73)
- # bristol-clojurians (2)
- # calva (9)
- # cider (25)
- # clj-kondo (7)
- # clojure (160)
- # clojure-dev (2)
- # clojure-europe (63)
- # clojure-italy (7)
- # clojure-nl (10)
- # clojure-uk (76)
- # clojuredesign-podcast (6)
- # clojurescript (63)
- # cursive (6)
- # data-science (3)
- # datomic (26)
- # duct (59)
- # emacs (1)
- # fulcro (12)
- # graalvm (17)
- # hoplon (23)
- # jobs-discuss (2)
- # kaocha (6)
- # meander (7)
- # off-topic (3)
- # pathom (2)
- # rdf (68)
- # re-frame (12)
- # reagent (20)
- # reitit (5)
- # ring (3)
- # ring-swagger (1)
- # shadow-cljs (14)
- # spacemacs (10)
- # sql (3)
- # tools-deps (30)
- # yada (9)
@seancorfield: any idea why this doesn't work with (builder/to-java
?
I suspect it has to deal with passing in a Map<String,String>
Can you put a small, self-contained example, with deps.edn
and a single .clj
file in a GitHub repo so I can take a look? I don't even know how to test the code you're showing without that information.
@seancorfield: here you go https://gist.github.com/johnjelinek/4e6ae543ba9db596461abc2a93101ac1
Thank you @U0FEHF1RS! I'll take a look tomorrow (I'm off work, so it'll be a good OSS day)
I hope you're staying safe re: COVID-19
The Bay Area is under complete lockdown. We're only allowed out of our homes to go to the grocery store/doctors etc.
So far, we're okay. But it's kinda "Mad Max" out there right now... shelves are empty of a lot of stuff...
@U0FEHF1RS I tried this in the REPL tonight and using :requestParameters
instead of :request-parameters
works.
And that makes sense to me for builder-based constructions.
java.data
doesn't do a-b
to aB
style translation, now that I look at it.
Also, you can simplify your code to this
(builder/to-java IntegrationOptions {:requestParameters {"a" "b"}})
java.data
will deduce the builder class and it will know how to construct it.
oic! Good find! I was pretty certain I was using train-case for other things, maybe not
also, when I was simplifying before without setting the builder-class
it was not deducing correctly
:kebab-case
, :snake_case
:headlessCamelCase
, :CamelCase
There are libs that use :kebab-case
(and turn then into .kebabCase
function calls) but java.data
is not one of them -- although that is not clear from the documentation (I need to work on that some more... maybe tomorrow?)
I've updated the java.data
README today to (hopefully) make it clearer that properties should be :camelCase
in general.
Anyone know of any other tutorials like this? It's invaluable https://www.exoscale.com/syslog/clojure-application-tutorial/ https://github.com/exoscale/exopaste
There is another one, which walks you through building an e-commerce experience. Let me find it.
If you interrested by Clojurescript and SPA too, you have this excellent course https://www.learnreagent.com/
The first 1h are free : https://www.jacekschae.com/learn-reagent-free
Ah and after learning Reagent, of top of that, you can also watch the Re-frame (2h video free): https://www.jacekschae.com/learn-re-frame-free
I tried recording myself going through that tutorial while I was watching my friend's kid, and the result was quite funny: https://www.youtube.com/watch?v=S0zeha5kukQ&t=693s
I have a lot of atoms, often changing one leads to changing others which again need to change others. Like if A is changed B needs to be changed which means C needs to be changed and so-on. This feels like an antipattern. Is it? Does it have a name? Are alternatives discussed somewhere? I am considering using a rule-based system to find out what changes need to be made all at once and then doing them, in succession.
First, it sounds like maybe you could use one atom and keep these values as keys in a map which you will update.
Second, you can let the state live in the scope of your process (in the computation sense, not OS sense), i.e. if all those atoms were bound variables inside a loop, you wouldn't need to change them, but to just recur
What was the reason to use atoms? Do you have a huge data structure that you wanted to divide, or do you want to model a bunch of processes connected together?
Okay; but the values in the map depend on each other. If the value belonging to :A is changed then the value belonging to :B should change.
I use atoms to have data in a global state which is visible to others. I want to make my system extensible (e.g. add a new widget to the dashboard which shows some new aspect of the data). Then all the data in my system needs to be visible to others. The splitting up into different atoms was because if one changes then others need to change.
Yes, and if you save them all in keys you can keep as configuration the relations which describe which updates need to occur (as another map?) Also for the use case you're describing, you can use something like what I wrote https://github.com/bsless/more.async/blob/master/src/main/clojure/clojure/more/async.clj#L250 to create a sort of push/pull state, which everyone can query, can be updated from outside, will always be consistent and is contained inside a computational process. But think about what fricze said about perhaps modelling them as a bunch of processes communicating with each other, then the logic of who updates whom will be in the topology of your connectivity
I will read more up on processes, thanks. I have never used queues myself (directly at least 😳).
> queues Queues are great. Highly recommend getting to know core.async and watching The Language Of The System
Thanks both of you. I will read https://www.braveclojure.com/core-async/ and ask some more newb questions afterwards :) @UFJD2TV46 I in the hammock-phase of building a workflow management system, like snakemake or nextflow. It will have a browser UI :)
btw this can be done without atoms if you have an event flow design: you make a function that takes an immutable map of data, does some updates, then passes it to your consumers (maybe a list of functions defined by third parties) and lets them attempt updates (which you then validate and accept or reject)
this can be done as a reduce inside a reduce
the outer reduce consumes a lazy-seq of "inputs" (from whereever...) as data, the inner reduce passes a state through a series of functions (the outside consumers)
I wouldn't use core.async unless some aspect of your domain requires out of order / async execution. Async introduces massive brittleness and makes bugs much harder to find, it leads to unintuitive code that's difficult to maintain. Only use it if you can prove you need it.
that said, if your domain requires async execution, core.async solves coordination problems very nicely
(but it's not a magic juice you pour in your app to make it faster)
Thanks noisesmith 🙂 Timothy Baldridge (formerly cognitect) made the same points about queues here: https://www.youtube.com/watch?v=096pIlA3GDo
Basically queues introduce non-determinism
right, core.async is a nice DSL over threads and queues, if you look at it from far away and squint in a certain way :D
also, when Tim Baldridge gave his clojure/west talk a few years back about core.async, I was working on an app in which I had foolishly used core.async (incorrectly, in many aways), and his advice about how it makes things more brittle and how and when to properly use it helped me turn the app into something much more stable (afaik that app is still in use without dev support today)
hey, i'm having issues with property-based-testing using test-check
, trying to test a simple-custom tokenizer, which returns vector of tokens,
(def alphanumeric-prop
(prop/for-all [text (gen/generate gen/string-ascii)]
(let [res (first (tokenize text))]
(and (<= (count res) (count text))
(some? (re-find #"^[a-zA-Z0-9]*$" res))))))
this leads to Assert failed: Args to tuple must be generators
(gen/generate gen/string-ascii)
should return a string, how can I get it as a generator and not a string?Hey, try this:
(def alphanumeric-prop
(prop/for-all [text gen/string-ascii]
(let [res (first (tokenize text))]
(and (<= (count res) (count text))
(some? (re-find #"^[a-zA-Z0-9]*$" res))))))
You don’t have to call gen/generate
there 🙂
gen/generate
returns a value given a generator, but prop/for-all
expects the generator itselfawesome 🙂
So why should I use gen/sample / gen/generate at all?
It is useful for quickly checking out what a given generator generates from the REPL 🙂 It is not used when writing properties or when writing your own generators
hey, btw - are you familiar if this kind of testing is performed in industry? I'm new to it and curious if to add it on my team
And another one 🙂 what are some 'default/pattern' properties you are testing? I'm following this https://dev.to/jdsteinhauser/intro-to-property-based-testing-2cj8 which has some nice examples, but any other source can help out (just some reference when you code and get tired..)
I want to parse yaml file and change some values. How can i do that with and without using any yaml parsing library?
To me parsing implies you want to build a data structure out of the text. The way I normally do that is use a parsing library, or build a parsing library for more esoteric things. If you just want to change some values, treat it as a stream of text and change the values with regex or the string functions.
Perhaps an example input and output would be helpful so we can see what specifically you want to do?
I have done it using slurp clojure.string/slurp
and clojure.string/replace
. Thanks 🙂
is this https://github.com/puredanger/startup-time relevant with Leiningen?
it is conceptually the same, but the mechanics of how to do it will be different, and I have not figured that out
but maybe someone that does leiningen stuff could doc that
clojure.data.csv/write-csv
has a quote?
keyword arg that takes a predicate which decides whether to quote a string
I want to quote all strings, but using the identity
function as my predicate seems a little unclear to me. Is there a better way?
you are the man! awesome