This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-23
Channels
- # aleph (1)
- # architecture (4)
- # aws (7)
- # beginners (249)
- # boot (17)
- # calva (4)
- # cider (30)
- # cljdoc (7)
- # cljs-dev (1)
- # cljs-experience (3)
- # clojure (69)
- # clojure-dev (7)
- # clojure-europe (1)
- # clojure-italy (7)
- # clojure-japan (15)
- # clojure-spec (6)
- # clojure-uk (39)
- # clojurescript (51)
- # cursive (31)
- # data-science (4)
- # datavis (1)
- # datomic (40)
- # dirac (67)
- # duct (8)
- # editors (15)
- # emacs (9)
- # events (3)
- # figwheel-main (2)
- # fulcro (157)
- # juxt (4)
- # kaocha (11)
- # lein-figwheel (1)
- # off-topic (31)
- # pathom (18)
- # re-frame (4)
- # reagent (2)
- # reitit (16)
- # remote-jobs (1)
- # shadow-cljs (11)
- # specter (2)
- # speculative (1)
- # tools-deps (27)
- # vim (1)
- # yada (2)
Hello. Working on a piece of genetic programming, and I have the situation where I want to have a set of symbols that will be placed in a list. Later when I am evalling that list as a function, I would like to be able to set the values of those symbols, with something like a let
example my program evolves a function (* (- 4 x) y)
. I would like to be able to provide values for x and y when I am running my fitness function
Except I don't have values for x and y at first, and need to provide/define them later
Okay, no, that is not it.
I am trying to evolve programs, so I have a function that builds nested lists, ensuring that the first argument is a function, and any subsequent list items are either valid s-expression or terminals like 1
I'm seeking a way to do two things.
One, include terminals like x
or y
in the set of possible chosen values.
Two, be able to call an evolved function, with the values of x and y present.
I would like to avoid using state, and having every 'x' terminal be "look up the value in an atom" but that could work
it seems refs or vars are close, but then I am unsure of how to use them precisely. I'm going to go read up on them
since you are building up a clojure form to be eval
ed, what stops you from wrapping the whole list in a
(let [x ... y ...] ...)
you could use with-local-vars
too (which is almost never used in Clojure)
What is the reason for not being able to use java static functions like clojure functions? As an example, I want to do this: (every? Character/isUpperCase [\a \b \c]), but am told that Clojure is āUnable to find static field isUpperCase in class java.lang.Characterā. consequently I have to wrap it like this: (every? #(Character/isUpperCase %) [\a \b \c])
An unsatisfying but true answer is "Because Rich Hickey designed it that way", leading immediately to the question "Why did Rich Hickey design it that way?" I do not know the answer to that question, but suspect it may have something to do with the JVM mechanisms chosen for function calling, versus straight JVM method calls, and efficiency.
Or perhaps also the flexibility rather than efficiency of Clojure function calls, i.e. having variable number of args.
https://stackoverflow.com/a/35200594/4379329 has a decent explanation
with MethodHandles now, it might be more feasible to build this into the compiler directly now
I have an issue with a quiz from 4clojure http://www.4clojure.com/problem/55
My solution to the problem works on my host.
user=> (defn solved? [f] (= (f [1 1 2 3 2 1 1]) {1 4, 2 2, 3 1}))
#'user/solved?
user=> (solved? #(->> % (group-by identity) (into {} (map (fn [[k v]] [k (count v)])))))
true
However, the function #(->> % (group-by identity) (into {} (map (fn [[k v]] [k (count v)]))))
doesn't pass on 4clojure website with the following error message: clojure.lang.ArityException: Wrong number of args (1) passed to: core$map
Is it a version issue? Any idea?
Very likely http://4clojure.com is running an older version of Clojure that doesn't have transducers.
Based on https://github.com/4clojure/4clojure/blob/develop/project.clj it seems to be running Clojure 1.4 perhaps? I would have expected someone to have updated it a bit in the last six years... No sure who maintains it these days.
Thanks @seancorfield Could you suggest me another implementation for the problem without using transducer?
Sure, just transpose the into
/`map` calls to avoid that arity.
(solved? #(->> xs (group-by identity) (map (fn [[k v]] [k (count v)])) (into {})))
(not sure if I typed that right, but that's the general idea)
user=> (solved? #(->> % (group-by identity) (map (fn [[k v]] [k (count v)])) (into {}))) true
Your (into {} (map (fn ...)))
form gets the expression threaded into the last argument position of the into
call, but your map
call only has one arg -- the function -- so that is valid with transducers (but was invalid before).
So you get (into {} xform expression)
where xform is the transducer returned by the 1-arg map
call.
Perfectly explained. I didn't even mean to use transducers when I came up with my previous implementation. Now I understand that I accidentally used the form of (into {} xform expression)
.
Although I met your version of implementation without transducers to workaround the old version of 4clojure, I think yours look more elegant and simpler. Thanks for your lesson.
BTW, can I run a clojure with a specific version with lein repl
, say, clojure 1.4.0 on my host for a testing and debugging purpose?
hey guys, i want to play around with clojure spec, so i've generated a project with lein
, my problem is that i can't get the repl to invoke functions i've created š
(ns demo-spec.core
(:gen-class)
(:require [clojure.spec :as s]
[clojure.spec.test :as test]))
(defn my-index-of
"Return the at which search appear in source."
[source search]
(str/index-of source search))
(my-index-of "foobar" "b")
(apply my-index-of ["foobar" "b"])
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
(defproject demo-spec "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.10.0"]]
:main ^:skip-aot demo-spec.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
You did not see any error messages when you ran lein repl
? When I try to reproduce what you have done, it says there is no such namespace clojure.spec
, which should be instead clojure.spec.alpha
, and similarly clojure.spec.test.alpha
. Also there should be a require of [clojure.string :as str]
or else the str/index-of
symbol is not resolved.
[clojure.main main main.java 37]]}
nREPL server started on port 46065 on host 127.0.0.1 -
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.10.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_191-b12
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
What is above the first line you pasted?
That looks like the last line of a stack trace, which I saw, where the first few lines had an error message
If you see lines like that, it can be a sign of a problem.
sure, np
For reference: I ended up with a solution to my issue like so
(defn expression-to-function [arguments expression]
(eval (list 'fn arguments expression)))
with arguments being a list of quoted symbols.Also this isn't necessarily a problem, but you should be able to do experimentation without using (:gen-class)
, aot, or mentions of uberjar in your project.clj file. You might need such things if you want to deploy a compiled Clojure application, but for REPL experimentation they are not necessary, and can in some scenarios cause issues.
@andy.fingerhut i did those changes you mentioned and it's working fine now, thank you š
Is there any handy way to transform a map with namespaced keys, like this:
#:funky-cool-aid {:color :purple}
to just {:color :purple}
? I know one can use destructuring and create a new map but my version of that is quite verbose.(reduce-kv (fn [m k v] (assoc m (keyword (name k)) v)) {} your-map)
should do it
Or (into {} (map (juxt (comp keyword name) identity) your-map))
if you're feeling sassy š
@seancorfield thank you, I'll have a look at both, it will be used quite frequently so i'll add them to danger-util āļø
(I should resist trying to write a point-free version at ten at night)
7:04 in sweden š
My second attempt was wrong -- I'd need a bit more in there
(into {} (map (juxt (comp keyword name key) val) your-map))
maybe something like that... I should open a REPL back up...
i just tried it, it works with the updated version š
user=> (def your-map #:funky-cool-aid {:color :purple :taste :grape})
#'user/your-map
user=> your-map
#:funky-cool-aid{:color :purple, :taste :grape}
user=> (into {} (map (juxt (comp keyword name key) val) your-map))
{:color :purple, :taste :grape}
user=>
yupAlthough I think it's more that Grape Kool-Aid tastes "purple flavor" š
I don't advise the point-free style really. Just wanted to show it was possible.
š thank you for the time @seancorfield
I have a map where each value is an array of int
s. For example: {:a [1 2 3], :b [4 5 6]}
I want to update this map so that the arrays no longer contain even numbers: {:a [1 3], :b [5]}
.
What is the idiomatic way of doing this?
@r.natarajan35 one way of processing maps keys and values is to use reduce-kv
e.g
(reduce-kv (fn [m k v] (assoc m k (filterv even? v))) {} {:a [1 2 3], :b [4 5 6]})
oh wait, no longer contain even numbers
s/even?/odd? in the above
another common approach is to use map-vals
, although it's not in core, it's commonly implemented
or a list comprehension, see this stackoverflow answer https://stackoverflow.com/questions/1676891/mapping-a-function-on-the-values-of-a-map-in-clojure
@danieleneal Oh wow, thanks! I really like the list comprehension version, it makes what i'm doing very clear to read
there was a thread a while back
Probably eastwood, I'd say
nope, sorry š
@r.natarajan35 just as an alternative, hereās a Specter solution:
user=> (def a {:a [1 2 3], :b [4 5 6]})
#'user/a
user=>
user=> (setval [MAP-VALS ALL even?] NONE a)
{:a [1 3], :b [5]}
Question about destructuring of nested maps - why the outermost key is specified last in such expressions? E.g., let's say I have
(def data {:platform "Windows" :type {:name "2008 R2" :edition "Standard"}})
This works:
(let [{{:keys [name edition] } :type} data]
(println name edition ))
2008 R2 Standard
but not this:
(let [{:type {:keys [name edition] }} data]
(println name edition ))
Syntax error macroexpanding clojure.core/let at (form-init5616907436889296336.clj:1:1).
[...]
one pragmatic reason is that this means you can use the same key for multiple bindings:
ser=> (let [{[{:keys [a b c]}] :maps [_ map2] :maps} {:maps [{:a 0 :b 1 :c 2} {:a 33}]}] {:a a :b b :c c :map2 map2})
{:a 0, :b 1, :c 2, :map2 {:a 33}}
if the normal key / value order was preserved, the map wouldn't be legal - you can't use the same key twice
@sy_borg thatās the syntax described here: https://clojure.org/guides/destructuring#_associative_destructuring
(let [[{{:keys [name edition] } :type} data] ..)
: it takes the value of :type
in data
and then you do an additional destructuring on that
Yeah, map destructuring is done in pairs, and in each pair the thing you're destructuring is on the right hand side and the symbols/names that you want to bind it to are on the left hand side. This is similar to how in a let binding, the thing is on the right hand side, and the name on the left, you'd say (let [a 3] a)
@danieleneal yes, I would think so if it was about data
symbol position, but it's about a key
(ns my-app.database)
(def database (atom {}))
(defn reset-database [] (reset! database {}))
(defn add-record [table record]
(swap! database update-in [table] conj (into {} record))
{:ok record})
(defn remove-record [table record]
(swap! database update-in [table]
(fn [records]
(remove #(= record %) records))))
(defn get-all-records [table] (get @database table))
(defn get-record-by-id [table id]
(->> (get-all-records table)
(filter #(= id (:id %)))
first))
(defn update-record [table id update]
(let [record (get-record-by-id table id)
updated-record (merge record update)]
(swap! database update-in [table] record updated-record)))
change your db to use the id as an index and it would be alot easier but yea i think you would need to use a map
but the other way works too, youād just need to use a (map ...)
that checks if the id is correct then run the update when it is correct.
I would advise against using map
in that case. Map will iterate over every single entry in the DB.
(defn update-entry
[pred f coll]
(let [[coll1 [entry & coll2]] (split-with (complement pred) coll)]
(lazy-cat coll1 [(f entry)] coll2)))
(update-entry odd? inc [2 2 2 1 2 2])
;; => (2 2 2 2 2 2)
This seems like a decent way to update a single entry of a sequence, but obviously just using a map is much better.If Iām writing a small utility to replace all :smile:
shortcodes in a markdown document with the emoji characters, how should I be parsing it? Is there a parser combinator library someone could recommend or should I use a line-seq and regex?
Check out Instaparse (and the #instaparse channel)
Instaparse is good for turning text into data, e.g. parsing a programming language or a custom data structure DSL. For "search/replace" type scenarios, where you have mostly unimportant text and an occasional token you care about, I think a regex is better honestly.
@U0516PHE3 Thanks for the explanation. After I read the readme of it I realized it was a bit overkill and went with a function to replace the shortcodes line-by-line. It seems to work pretty well so far.
Hello, I am having issues running a Leiningen project in the repl within vscode via the Clojure extension. Where should I start to troubleshoot this?
version: Leiningen 2.8.3 on Java 1.8.0_191 OpenJDK 64-Bit Server VM
error:
Warning: implicit middleware found: cider-nrepl.plugin/middlewarePlease declare all middleware in :middleware as implicit loading is deprecated.
@U7J6AMWDR Is the project public, or could you share it with us?
The cider
part of cider-nrepl.plugin/middleware
refers to CIDER, a Clojure development environment for Emacs. https://github.com/clojure-emacs/cider
Seeing as you say you're using VSCode I wonder if there's something strange about how the project is being started.
@U050CT4HR it is just a newly generated project using Leiningen. I just didn't want to have to learn vim at the same time I am learning vscode. Any thoughts?
I don't have a ~/.lein/profiles.clj
folder. Any other thoughts? I set up Leiningen in the way described by the install docs - don't think there was anything unique about it
looks like it is related to an existing bug here: https://github.com/avli/clojureVSCode/issues/121
Is there a good analog to mocha's only
method (https://mochajs.org/) in cljs.test (or clojure.test for that matter)? I have ~100 tests and I'm getting tired of comment
ing out un-used tests and/or changing the regular expression on my run-all-tests
call.
While I'm at it, is there a good alternative to cljs.test? I'm pretty unhappy with it in a number of aspects, and I'm on the cusp of writing my own testing framework š
Looks like clojurescript support is pretty new, any idea if it works with shadow-cljs?
if you want to run a single test, you could give https://github.com/Olical/cljs-test-runner a try
say i really wanted to check whether a value was false like so:
(s/explain #{false true} false)
val: false fails predicate: :clojure.spec.alpha/unknown
:clojure.spec.alpha/spec #{true false}
:clojure.spec.alpha/value false
that is, i didn't want to use boolean?
. how would i do that?the fact that sets work as predicates relies on the set returning the arg if present, this doesn't work for nil or false
you can use #(contains? #{false true} %}
but that doesn't give you a free generator like a set does
you can use boolean?
here of course
maybe boolean? already has a generator defined? my spec knowledge is a little rusty
i'd like to use this as output for less-technical people, so i want really explicit error messages
I think "boolean?" is pretty self explanatory
@borkdude Some of the trouble is incidental and because of shadow-cljs, but off the top of my head:
- No way to target individual tests without writing code. You can target namespaces with a regular expression or run-tests
, but I'd really love command-line or local-code selection mechanisms (like kaocha offers)
- I've had trouble getting tests to exit with a 1 for ci purposes. I can't remember how I got that working, but I may have wrapped them with a bash script that parsed the output
- There aren't a lot of nice assertion methods. Not a big deal; it's easy to write your own, but is=
is the big omission here.
- Unless this was an artifact of shadow-cljs's test runner, stack traces get swallowed. If there's an error, I want to see the whole thing. As a result, I'm passing in a custom formatter that calls *print-err-fn*
.
@mfm Hum, there's a library for that, let me try an find it. Because shoe-horning simpler spec seems wrong.
ClojureScript 1.10.439
cljs.user=> (require '[clojure.spec.alpha :as s])
nil
cljs.user=> (s/explain boolean? true)
Success!
nil
cljs.user=> (s/explain boolean? false)
Success!
nil
cljs.user=> (require '[clojure.spec.gen.alpha :as gen])
nil
cljs.user=> (require '[clojure.test.check])
nil
cljs.user=> (gen/sample (s/gen boolean?))
(false true true false true true true true false false)
@jstaab cljs-test-runner should get you most of these things as well, I havenāt tried kaocha, itās cljs support is pretty new
@borkdude Yeah, just gave it a shot; it doesn't detect my dependencies as declared in my shadow-cljs.edn, so I'm looking for a way around that. I'll take a look at cljs-test-runner though; that might be closer to a happy medium.
youād have to put those deps in a deps.edn file or maybe you can point the cljs-test-runner to a different file, I havenāt tried and donāt know if shadow uses the same format as tools.deps
It's more leiningen-style, but I only use mvn deps so far, so I could maybe translate. Anyway, it's probably easier to just duplicate my dependency list. The one thing I'm a little worried about is whether either one will know how to import node_modules dependencies, since I think shadow-cljs gets pretty deep into resolution/externs stuff
so you're saying, i could gen/sample
some valid results to show the user? that's pretty cool
i agree that the spec that behaves correctly is boolean?
; i was looking for a spec whose explanation says, "value foobar
is not one of #{false true}
"
@borkdude If the audience is an end-user, boolean is bad feedback. You want the message to be simpler, and more contextualized to the app and the domain.
the intended audience is sort of an admin dashboard for our "tech support engineers" who have to diagnose mis-parsed client data. so it'd be great to have "value foobar
is not one of #{some acceptable values}"
that is, my expectation is that they can look past some syntactic idiosyncracies ( #{} and the like ) but i'd still like it to be really really concrete
yeah i've been reading into that a little bit. and, in fact, using gen/sample
is a great idea
you could also implement an explaining layer that maps a spec to a freeform string customized to your audience
{boolean? "should be either 'true' or 'false'" number? "should be be a machine readable number like 1 or 3.14"}
etc.
you can get pretty far on specs almost doing the right thing with explain, but I'd assume you'd keep getting more awkward messages and corner cases
I think that would depend on who is intended to interpret the message, if the reader isn't a dev (not to mention not a clojure dev), I'd expect a lot of awkward details
eg. even something like "string" can be confusing for a technical user who isn't a dev
i guess writing your own spec introspection util is one way to get this "right", so that you can optimize for your specific audience
in that case you could also write your own predicates and give them less technical names
that's true
@mfm Sorry if I missed this, but if you are in a position where you can define your own spec for boolean, you can use expound to set a custom error message
(require '[expound.alpha :as expound])
(require '[clojure.spec.alpha :as s])
(set! s/*explain-out* (expound/custom-printer {:print-specs? false}))
(s/def ::boolean boolean?)
(expound/defmsg ::boolean "should be either true or false")
(s/explain ::boolean false)
;; Success!
(s/explain ::boolean nil)
;; -- Spec failed --------------------
;; nil
;; should be either true or false
;; -------------------------
;; Detected 1 error
You canāt associate a message with the boolean?
predicate itself, but you can associate it with spec keywords that are predicates
@bbrinck Ah, now I get why you wanted those keyworded specs in speculative š
I havenāt yet used them in speculative, but when I get some more free time, I have an idea about building a set of beginner-friendly messages for lots of core predicates
awesome. I think I want a custom KLIPSE repl (faster performance) online with exactly that too
Outside of the beginner context, I know that lucinia uses this functionality to clarify some complicated specs https://github.com/walmartlabs/lacinia/blob/d351d3c4dd9a0aad5cd078c87fabed0df2b14471/src/com/walmartlabs/lacinia/expound.clj#L22-L28
@bbrinck Iāve been wondering if expound can handle (s/or :f ::foo :b ::bar)
well, no need to put composites in their own keyword right?
This is what happens by default:
(s/def ::foo int?)
(s/def ::bar string?)
(s/def ::foobar (s/or :f ::foo :stuck_out_tongue: ::bar))
(s/explain ::foobar :abc)
;; -- Spec failed --------------------
;; :abc
;; should satisfy
;; int?
;; or
;; string?
;; -------------------------
:D :stuck_out_tongue:
@bbrinck yeah, so if you would have custom messages for either spec they would still be printed here?
(expound/defmsg ::foo "should be an integer")
(expound/defmsg ::bar "should be a string")
(s/explain ::foobar :abc)
;; -- Spec failed --------------------
;; :abc
;; should be an integer
;; or
;; should be a string
;; -------------------------
it would also be helpful to have a 4clojure instance running with expound + speculative I bet
Hello - I've tried uploading a simple project to Clojars (cljblpapiwrapper). That project uses a local jar file (non Clojure) as a dependency, declared in :resource-paths
in project.clj. Now upon trying to use this project somewhere else, it fails to locate the jar file. How should I go around the problem? Can I publish the jar on Clojars separately? Thank you,
the natural way to share deps is to make maven artifacts, and it's straightforward to use clojars for that, sure
or they could check out the repo and run lein install
If a clojure file defines a private function like (defn- a-func [] true)
is there a way to call it like (in-ns 'my-private.ns) (my-private.ns/a-func)
?
it is a bad idea to put in-ns forms in the middle of a source file unless you really know what you are doing
You donāt need to deref - vars are invokable
(which manually does the bits the compiler would do for you if it wasn't so worried about things being private)
Hmm shouldnāt that work? https://github.com/weavejester/environ/blob/master/environ/src/environ/core.cljc#L80 Iām trying to run the following in a REPL
(require 'environ.core)
(in-ns 'environ.core)
(def env (#'read-env))
When I run it I get āunable to resolve var read-env in this contextā.