This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-10
Channels
- # announcements (5)
- # aws (18)
- # babashka (1)
- # beginners (81)
- # calva (7)
- # chlorine-clover (1)
- # cider (5)
- # cljs-dev (8)
- # clojure (125)
- # clojure-dev (1)
- # clojure-europe (31)
- # clojure-italy (3)
- # clojure-nl (2)
- # clojure-norway (1)
- # clojure-spec (5)
- # clojure-sweden (1)
- # clojure-uk (31)
- # clojurescript (85)
- # code-reviews (1)
- # core-async (17)
- # cursive (39)
- # datomic (16)
- # emacs (1)
- # fulcro (6)
- # java (16)
- # kaocha (2)
- # luminus (4)
- # malli (2)
- # off-topic (65)
- # pathom (3)
- # re-frame (11)
- # reagent (5)
- # remote-jobs (1)
- # rum (5)
- # sci (10)
- # shadow-cljs (24)
- # spacemacs (4)
- # test-check (3)
- # tools-deps (22)
- # xtdb (15)
if i have a nodejs file can i just read it into my repl as code? or does it have to be packaged somehow to do that?
you can require / load it via the mechanisms node offers - node has its own version of require with its own rules about where files need to be
and for a js file you can use that API directly instead of the cljs layer
@mathpunk if you will be running with node as your js platform, this should be easy to translate to cljs https://nodejs.org/en/knowledge/getting-started/what-is-require/
it's not compatible with the browser of course
[1 2 (range 3 5)]
vector resolves as expected to [1 2 (3 4)]
'(1 2 (range 3 5))
, i.e. escaped list, resolves to (1 2 (range 3 5))
which is suprising, because range is not eval'ed. I tried to escape it with or @ but it does not make much sense to me, nor does it help either.
if you use ` instead of ', you can use escaping
Practially I can use the vector, but I just want to undesrtand if there's a way to eval the (range) in this context
you can also just use list
(list 1 2 (range 3 5))
- the common newcomer mistake is to think ' is a thing for making lists
you can also use eval explicitly, but the real fix is not preventing the initial eval in the first place, and ' is the thing that prevents eval
I'm having to interop with some java code, just found that HashMap is not considered a map so I need to turn it into one. Seems I can do (into {} (HashMap.))
and that seems to work, but wondering if there is a preferred way (ideally) that would avoid duplicating the whole map?
clojure doesn't copy the HashMap key and vals, it only creates new map-entry objects to put each pair in
there's very little implicit copying in clojure, as idiomatic code assumes that values are immutable, so copying defensively is rarely needed
also, you can use get
on a HashMap, it's just things like conj
assoc
and dissoc
that require clojure maps
(ins)user=> (def hm (java.util.HashMap.))
#'user/hm
(ins)user=> (.put hm "a" 0)
nil
(ins)user=> hm
{"a" 0}
(ins)user=> (merge {"b" 1} hm)
{"b" 1, "a" 0}
hm is a java HashMap, the final result is a clojure map, no explicit conversion was needed(merge used get under the hood, that was fine, didn't require any copying, it does create new map-entry when merging, there's no way not to do that, java class or no)
Thanks, I wanted to use keywordize-keys but it failed to change anything since it asks if it's a map, though I've just realised I'll have to also recurively into
it first to make it work since it appears to be a map of maps
yes, that makes sense - but also, keywords on input data are often a bad idea
use keywords if you are dealing with data literals from code, of course, but in many cases its simpler and less error prone to keep the original data type of the keys
@ULNRSUK8C and to be clear, that into
call doesn't copy the map contents, just the skeleton (though in this case you do need to do so recursively)
if you fear a performance bottleneck, you can keywordize within the into itself, instead of walking/reconstructing the key twice
it's just unfortunate that it doesn't fit the same pattern as everything else here if I don't keywordize. I'm getting the value from a kubernetes client api and most come back as beans so I have used clojure/java.date from-java which gets me keywordized maps. In this case it's a custom resource so I get the map of strings to maps/strings
To be honest I'm not sure performance is any issue, I was just wondering if there was a more idomatic way of doing it, so I think I'll do as you say with the walk->into
thanks 👍
(defn clojurify [m]
(into {} (map (fn [[k v]]
[(if-not (string? k)
k (keyword k))
(if-not (instance? java.util.Map v)
v
(clojurify v))])
m))
something like this would help avoid the double reconstruction(first draft, probably has some shallow bugs)
thank you, that's very helpful! 🙂
spearate question, why do you prefer if-not in the above? Is it just a style choice to have the recursion last or something?
it would probably be better code if you had a seq of predicate/key-transform pairs and a seq of predicate/val-transform pairs, then you have something reusable for foo->clojure conversion
my first preference is for the first branch of a conditional to be the short one
also, to put recursion last, which tends to be a side effect of that
which makes recurring on the wrong branch stand out
or failing to simplify while recurring, also stands out if you follow that rule
especially since we only allow recur
on tail calls, it's intuitive that a tail call should go as far down and to the right as possible
it's kind of a lispy rule of thumb thing
makes sense, hadn't thought about the branch length, the recursion symmetry is nice
another aspect: humans construct a stack as they read forms
if the short form comes before the long form, you do less work moving up and down the stack :D
(Germans likely have more practice with stack operations and are less limited by this issue)
😂 cheers for the help
what’s the best way to ensure atomic channel writes? is wrapping it in an atom a good idea?
what kind of channel?
putting side effecting operations inside an atom is the opposite of a good idea
"atoms" ensure data consistency but do not lock, instead they run operations speculatively and retry if there was concurrent modification
as in clojure core.async?
if so, channel writes are already atomic (unless you mean something different than I do by atomic...)
if the bytes need to go together, they probably shouldn't be mixed on the same channel as other bytes
or they should be tagged so they can be separated and separately consolidated
you can't block other users of a channel
(I mean, you can do it accidentally by clogging up all go blocks, but even then you haven't blocked usages of channels outside go blocks)
one idiom:
(async/thread
(loop [acc []]
(let [x (get-from-place)]
(if-not x
acc
(recur (conj acc x))))))
runs in its own thread, because IO inside go blocks just clogs things up and doesn't benefit from core.async
but maybe you want to group every N bytes and send to a channel (use put!
for that, pass in a channel when creating the thread)
there's a few variations, but that's a good template for getting IO data into core.async
@gtzogana also, since this is #beginners - consider that you can make everything a lot simpler and running (future (some-code that returns all contents))
and then calling deref later to get what it found
core.async makes coordination simpler, but often the even simpler thing is to not need coordination
Hi, everyone. I'm working on migrating a hobby app I have on Google App Engine to Clojure/ClojureScript. I was able to deploy a simple web app by creating an uberjar with https://github.com/tonsky/uberdeps. But when I try this with a more complicated app, I get a strange error that I don't understand:
Syntax error compiling at (clojure/tools/reader/reader_types.clj:1:1).
No namespace: clojure.tools.reader.impl.utils
I can use the same uberjar to launch the app locally, this error only happens on App Engine. Also, I confirmed that clojure/tools/reader/impl/utils.clj
is in the uberjar.
Any ideas?
Thanks!I've been struggling with this for a little while, but of course the moment I post it, I figure it out. I think I had insufficient memory on my App Engine instance. I tried adjusting the -Xmx
and -Xss
flags, but ended up just bumping up to an instance class with more memory, and things seem to be working.
I was originally using the free F1 instance, which has a 256 MB limit. I had set -Xmx128m -Xss256k
, but I was getting stack overflows, so I bumped it up to -Xss512k
. When I switched to an F2 instance, which has a 512 MB limit, it works, and seems to be using about 300 MB of RAM.
Any tips for keeping memory usage down?
And 128m isn’t reasonable for a Clojure app in most cases - 256m is minimum; likely more if it’s something at least slightly serious (your app might work but you will pay a performance penalty because of limited memory)
I imagine doing a native compile using graalvm would reduce the memory usage
That's better reserved for simple (command line) tools rather than a standard approach of doing things
Heroku free tier uses 512 container images. This is how I deploy a deps.edn project on Heroku free tier (via CircleCI) https://practicalli.github.io/clojure-webapps/projects/status-monitor-deps/deployment-via-ci.html