This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-20
Channels
- # adventofcode (38)
- # announcements (8)
- # aws (4)
- # babashka (131)
- # beginners (263)
- # calva (2)
- # clj-kondo (12)
- # cljdoc (12)
- # cljsrn (3)
- # clojure (122)
- # clojure-europe (3)
- # clojure-finland (2)
- # clojure-nl (13)
- # clojure-uk (80)
- # clojured (1)
- # clojuredesign-podcast (3)
- # clojurescript (78)
- # core-async (19)
- # cursive (19)
- # datomic (7)
- # duct (10)
- # events (1)
- # fulcro (7)
- # graalvm (12)
- # graphql (3)
- # juxt (4)
- # malli (10)
- # music (3)
- # nrepl (4)
- # off-topic (25)
- # pathom (4)
- # pedestal (1)
- # re-frame (78)
- # reagent (8)
- # shadow-cljs (91)
- # sql (8)
- # vim (3)
- # xtdb (2)
Can someone explain me how and if this should work in Clojure?
(let [{a :a
{b :b} (name a)}
{:a :a
"a" {:b :b}}]
(println "value of b" b))
It seems the bound value of a is used in the "second" binding, but since it's a map destructuring, the bindings aren't ordered maybe, so I'm puzzled if this would work at all
whoa, that definitely smells like undefined behaviour, I had no idea that was valid syntax
But reordering the keys in the destructuring form breaks it:
(let [{b a, a :a} {:a :x, :x :y}]
b)
;; Syntax error compiling at (src/repro.clj:4:1).
;; Unable to resolve symbol: a in this context
(let [{_x :a
b1 :a
c :a
d :a
e :a, f :a, g :a, h :a, i :a
{b :b} (name _x)}
{:a :a
"a" {:b :b}}]
(println "value of b" b))
Syntax error compiling at (form-init191682565753033842.clj:6:15).
Unable to resolve symbol: _x in this context
When you create a map using {}
, it creates an array map if the number of items is <= 8. Otherwise, it creates a hash map.
With array map, the order and hence the behavior is well defined. With a hash map - no so much.
I'm confused:
(let [{a :a, b a, c b, d c, e d} {:a :x, :x :y}]
[a b c d e])
=> [:x :y nil nil nil]
Yeah, given your example, I retract my previous words about an array map resulting in a well defined behavior.
it makes more sense looking at the macroexpanded form of let
, which is just a "dumb" syntactical transform that doesn't know about symbol resolution
But the (let [{a :a, b a, c b} {:a :x, :x :y}] c)
is actually correct to return nil
. Because there's no :y
key in the map.
Issues with such destructuring only arise when there are more than 8 items. So OK, I retract my retraction. :D
That's true. Maybe it's fine in some cases, but it seems unnecessary for the simple case of destructuring. It can be written in a not much less concise form without relying on anything. And it will also be more readable.
If I understand the code correctly, the destructuring goes from "right to left" in the given code, but that, I think, should be regarded as an implementation detail. One place where that potentially matters in when you destroy two things to the same variable. That is problematic but at least not more surprising than anything else. One way to give a actionable insight from clj-kondo could be to highlight if variables are destructed to twice, that seems like it should be treated like a mistake to me. Also if you rely "destruction targets" in the destruction expression, that's probably a mistake as well.
Wow, these examples are fun. My brain keeps turning back to them thinking that I still didn't get something.
agreed, you should not rely on this working
there is actually a ticket about this I think
not it, but similar: https://clojure.atlassian.net/browse/CLJ-1613
also not it, but similar: https://clojure.atlassian.net/browse/CLJ-1881
I did not find a ticket specifically about this (not involving :or)
WDYT of the following pattern for authoring macros that work in clj + cljs + self-hosted cljs?
(defmacro foo [compilation-target]
(case compilation-target
:clj :clj
:cljs :cljs))
(foo #?(:clj :clj
:cljs :cljs))
The targeted problem being: determining within the macro what the compilation target is - clj or cljs?
I normally use (-> &env :ns nil?)
but that's not an official API
Won't work as intended: for vanilla cljs, macros run in the JVM and reader conditionals will resolve to their :clj branch
Right.
thheller in his article about macros uses exactly what you use normally - (if (:ns &env) %cljs-branch% %clj-branch%)
: https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html#gotcha-4-clj-macros
Dunno, seems like everybody uses it. And Clojure[Script] is not really infamous for any backward incompatible changes.
But I get what you're saying - I cannot find any official documentation on it. Everyone just says "it works, that's how it is".
I do perceive in Clojure core a commitment to not break APIs, and no particular commitment to not break non-APIs (which is quite reasonable, and sets a precedent to not rely on random hacks)
For completeness - there's this answer reflecting it's an open problem https://stackoverflow.com/a/42209528/569050
Its suggested solution isn't that reliable - a JVM repl may have required that cljs.analyzer
ns for "reasons". Has happened to me
hello, has anyone used GitHub Actions to run tests on a clojure project with leiningen, where a couple of the project dependencies are in a private S3 bucket? locally i've been using s3-wagon-private
and aws access/secret keys in a ~/.aws/credentials
file.
i was hoping something like this would do the trick:
name: Clojure CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Install dependencies
run: lein deps
- name: Run tests
run: lein test
but lein deps
returns a Could not transfer artifact ... Access Denied (Service: Amazon S3; Status Code: 403;
i've added the aws access/secret keys to the github repo, Settings -> Secrets, but i feels like i'm missing a step somewhereif you can't use the same credentials, you can assume a role with the same policy and give it a shot locally
or add a call to aws sts get-caller-identity
after you configure credentials to make sure everything is ๐:skin-tone-4:
(you may have to delete a private jar from ~/.m2/repository to make sure that lein re-pulls it down locally)
good call yeah, i've wiped the local repo in ~/.m2/repository, used the same access/secret key pair locally and have gotten a successful download
github has masked the Account
number, ***
, but the UserId
and role part of the Arn
match up
[s3-wagon-private "1.3.1"]
i could bump that to the latest, 1.3.3
and see what happens
the s3 region is of critical importance when accessing s3 buckets - you had "eu-west-1" above - is that where the bucket is?
can you paste the config and redact the bucket?
:plugins [[s3-wagon-private "1.3.1"]]
:repositories [["releases" {:url " "
:no-auth true
:sign-releases false}]])
another thing to debug is assume the same exact role then:
aws s3 cp --recursive /tmp
there's something else at play somewhere...
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
thanks for your help @U050ECB92, i've no fear that the github action itself and the project.clj
should work at this stage. i'll have to do my homework on how we're managing access to that private bucket, but for now it's beer o'clock on a friday evening. thanks again ๐ป
Hi, I'm working on adding support for schema.core/defn
to clojure-lsp. An example call is
(s/defn stamped-names :- StampedNames
[names :- [s/Str]])
Can anyone think of other libraries' macros with a similar approach to annotating parameters? Basically looking for other examples where a "parameter" vector would need to ignore some inner elements.ghostwheel is kind abandoned, but there its successor guardrails
Reading the clojure.walk
api docs, and I came across this:
Note: "walk" supports all Clojure data structures EXCEPT maps
created with sorted-map-by. There is no (obvious) way to retrieve
the sorting function.
My initial thought is that the sorting function could be stored as meta-data on the map and used later? Just a thought.The Java implementation has a field storing the sorting function, so via appropriate kind of field access it is straightforward. It isn't published as a Clojure-level access function that I know of.
Do you have a link to that text you found?
Overview section at the top
@flyboarder Not sure what that means, but in a quick REPL test, it seems that walk supports sorted-map-by
user=> (clojure.walk/postwalk-demo (sorted-map-by > 1 10 2 20))
Walked: 2
Walked: 20
Walked: [2 20]
Walked: 1
Walked: 10
Walked: [1 10]
Walked: {2 20, 1 10}
{2 20, 1 10}
user=> (clojure.walk/postwalk-demo (sorted-map-by < 1 10 2 20))
Walked: 1
Walked: 10
Walked: [1 10]
Walked: 2
Walked: 20
Walked: [2 20]
Walked: {1 10, 2 20}
{1 10, 2 20}
at least nominally postwalk-demo is transforming nodes, it just happens to return the same node it received
ostensibly you could change the value of something in place and it would not re-sort it?
when I check the type returned by the postwalk, it's a clojure.lang.PeristentTreeMap
I'll try a version that inverts sign of the keys
(ins)user=> (clojure.walk/postwalk (fn [x] (if (number? x) (- x) x)) (sorted-map-by > 1 10 2 20))
{-1 -10, -2 -20}
(ins)user=> (type *1)
clojure.lang.PersistentTreeMap
that looks right to meit makes sense, if this works, then postwalk should work
)user=> (let [m (sorted-map-by >)] (into m {1 :a 2 :b 3 :c}))
{3 :c, 2 :b, 1 :a}
relevant clause of clojure.walk/walk cond form:
(coll? form) (outer (into (empty form) (map inner form)))
it might be the doc is stale on that point?
it calls into, into preserves your sort function