This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-11-09
Channels
- # aleph (3)
- # beginners (327)
- # calva (3)
- # cider (20)
- # cljdoc (59)
- # cljs-dev (40)
- # clojure (104)
- # clojure-dev (30)
- # clojure-italy (8)
- # clojure-nl (36)
- # clojure-russia (3)
- # clojure-spec (3)
- # clojure-uk (79)
- # clojurescript (54)
- # community-development (5)
- # cursive (28)
- # data-science (21)
- # datomic (35)
- # emacs (14)
- # expound (1)
- # figwheel (2)
- # figwheel-main (82)
- # fulcro (18)
- # graphql (13)
- # jobs (12)
- # jobs-discuss (38)
- # kaocha (8)
- # lambdaisland (1)
- # lumo (12)
- # off-topic (20)
- # onyx (4)
- # re-frame (51)
- # reagent (12)
- # reitit (8)
- # ring-swagger (1)
- # shadow-cljs (22)
- # slack-help (2)
- # spacemacs (6)
- # specter (16)
- # testing (3)
I need to embed a cljs repl into a webpage. There's no server support, everything needs to happen server side. Is lumo, klipse, planck, or something else the best choice?
For what you're describing you don't need any libraries, but Klipse might do what you want out of the box: https://github.com/viebel/klipse
Yes, I meant "everything happen client side." Thanks for inferring that. 🙂. Sure, will move to cljs.
is there any SLOC counting tool that works well with Clojure?
I tried a few and the best one (cloc) is still not great because it also counts docstrings as lines of code
the others don't even attempt to detect blank lines or comments instead
Not sure that there's much in the way of a future specific style. I think the idea behind the future is to 'lift' threading, etc into nice clojury value-orientation so that all you need to follow are your general style, best practice, etc guidelines
@andrea.crotti my cheesy solution: find . -name \*.clj -o -name \*.cljs -o -name \*.cljc | grep /\*/src/ | xargs cat | grep "^.*\S.*$" | grep -v "^\s*;.*$" | wc
ah actually there is https://github.com/aiba/lein-count
it seems that (.getClass obj)
is called via reflection. why is that? should it be possible without reflection, since getClass is there for all objects?
so we tried eval
ing 700kb of (generated) Clojure code and the compiler died with a stack overflow
known limitation?
usually it's solvable by breaking it appart and doing it chunk by chunk or just avoiding eval (better)
Ratio
is not part of edn
specification. In cljs repl, if you try to write a ratio, it throws Exception in thread "main" clojure.lang.ExceptionInfo: failed compiling constant: 1/2; clojure.lang.Ratio is not a valid ClojureScript constant. {:constant 1/2, :type clojure.lang.Ratio}
But if you (pr-str 1/2)
it returns "1/2"
, which is a "invalid" edn
( pr-str
should always print edn
, right?
transit-clj
read and write Ratio
transit-cljs
dont say anything about Ratio
Is it a tracked issue?
there are plenty of values from pr-str that are not parsible as edn
(eg. Exception, Object, arrays)
(pr-str (new Object))
=> "#object[java.lang.Object 0x45463dad \"java.lang.Object@45463dad\"]"
- It's a tagged'y thing. Can fit in the edn
spec.
- behaves in the same way clj
and cljs
(cant read by default)
- both transit throws
when tryies to serialize.speaking of transit - it does seem to handle 1/2 in a way that cljs could handle
(cmd)user=> (def baos (java.io.ByteArrayOutputStream. 4096))
#'user/baos
(ins)user=> (cognitect.transit/write (cognitect.transit/writer baos :json) 1/2)
nil
(ins)user=> (.toString baos)
"[\"~#ratio\",[\"~n1\",\"~n2\"]]"
So probably I will need to handle with
{:handlers {"n" (fn [v] (parse-bigint v))
"f" (fn [v] (parse-bigdec v))
"ratio" (fn [v] (parse-ratio v))}}
Nice. I will try to suggest some extra-docs on transit-cljs
READMEhave you tested? I would assume if clj transit generates #ratio, that cljs transit would read it
That's an interesting question - I was surprised to see that cljs couldn't handle 1/2
(str (transit/read (transit/reader :json) "[\"~#ratio\",[\"~n1\",\"~n2\"]]"))
=>
"[TaggedValue: ratio, [#object[Transit$TaggedValue [TaggedValue: n, 1]] #object[Transit$TaggedValue [TaggedValue: n, 2]]]]"
(pr-str (transit/read (transit/reader :json) "[\"~#ratio\",[\"~n1\",\"~n2\"]]"))
=>
"#object[Transit$TaggedValue [TaggedValue: ratio, [#object[Transit$TaggedValue [TaggedValue: n, 1]] #object[Transit$TaggedValue [TaggedValue: n, 2]]]]]"
It can handle. But it's a bit useless without some custom methodsfascinating
(transit/read (transit/reader :json {:handlers {"ratio" (fn [[k v]]
(/ (js/parseInt (.-rep k)) (js/parseInt (.-rep v))))}})
"[\"~#ratio\",[\"~n1\",\"~n2\"]]")
I will use something like thisyou can also do some protocol stuff. But then you always need to use your IToString/->str
and it need to be extended to bigint
, bigdec
, ratio
...
smells like a multimethod almost...
I'm surprised this isn't sorted already, frankly
I had a problem with bigint few months ago. My application simply stopped working because a number get too big and clojure turns it into bigint
I was wondering, what are -- in your opinion -- the bad parts of Clojure -- stuff you should not use, ever? And why?
To be clear, I am talking about things that you could stop doing today (or could be enforced by a linter), not stuff that would need changes to the language. I.e. if you don't like S-expressions, that doesn't qualify.
might be a better question for reddit or clojureverse, as it will probably get lost in the conversation here
So let's talk about the ns
form... :p
I don't see a lot of things that I would stop doing; I do see a lot of things than you can abuse (e.g dynamic Vars, lazyness, eval, macros...)
You are probably right, @U0BAS2E13
I have stopped using dynamic vars. When I need thread local state, I use java.lang.ThreadLocal, it's simpler and faster.
I’ve been using clojure for 10 years and have honestly tried my best to think of something… and I can’t really think of anything… struct
s are basically deprecated; simply because there’s a better mechanism these days but they still work fine…. :use
as an ns
form is also basically deprecated, and :refer :all
can be an anti pattern but sometimes it’s totally warranted.
declare
is definitely ok too; but it should only be used where you can’t restructure forms to break a mutual dependency.
So the only two things I can really think of is calling realized?
on anything other than future
/`promise`, e.g. a lazy-seq.
And I guess also #=
reader eval, but that also has a few uses.
So I think that just leaves us with a few standard Lisp aphorisms, like “eval is evil” (except where you need it — e.g. to implement a REPL), and don’t abuse macros 🙂
I think we’ll fix the realized? thing btw
and #= is officially not public so you shouldn’t use it anyways :)
I have often wondered what Rich’s biggest regrets about clojure might be… what he’d do differently if he could go back and do it again. I’m guessing putting protocols at the bottom would be quite high on that list (but he fixed that in clojurescript, right? 🙂)
open sourcing it?
just kidding ha ha! :)
lmao it’s funny you mentioned that… I almost said that too!
“Clojure would be great if it wasn’t for our **ing users” 😉
One has to wonder how many times you folk at Cognitect say this 😉
Clojure was always made to be shared. There’s no point in putting years of work into something just for yourself.
Of course, I’m just being facetious; we’re all very much in debt to your generosity!
Sure, clojure isn’t perfect… but I’d probably call the imperfections blemishes rather than warts, as they’re usually not that ugly. if we’re talking blemishes there are a few but nothing major… e.g. inability to add docstrings in defrecord
(because there’s no var for them), then sometimes you need to define a new constructor for them so you may want to mark the implicit constructor private (which you can do with alter-meta!
) so people don’t use it rather your one etc… I also wish spec had docstrings too… though hopefully that’s coming.
before I go dig, does anyone know what kind of rounding will happen here (format "%.2f" some-double)
seems like HALF_EVEN
I would be surprised if the docs for Formatter don't make it explicit
user=> (doc format)
-------------------------
clojure.core/format
([fmt & args])
Formats a string using java.lang.String.format, see java.util.Formatter for format
string syntax
nil
from the doc for Formatter:
The number of digits in the result for the fractional part of m or a is equal to the precision. If the precision is not specified then the default value is 6. If the precision is less than the number of digits which would appear after the decimal point in the string returned by Float.toString(float) or Double.toString(double) respectively, then the value will be rounded using the round half up algorithm. Otherwise, zeros may be appended to reach the precision. For a canonical representation of the value, use Float.toString(float) or Double.toString(double) as appropriate.
:thumbsup:
I find myself using the clojure REPL a lot for doing data manipulation - before I go implementing this myself, anyone know of an existing way to print data from the REPL but pipe it through a pager or less
or other interactive shell tools? I couldn't find anything, so I'll likely try to implement it myself - I'm probably either going to need to launch it as a child process from clojure and figure out how to hook the child's stdio to the REPL's stdio, OR maybe manipulate it on the readline/rebel-readline/rlwrap level...
@jesse.wertheim Haven't used it, but you may be interested in datawalk: https://github.com/eggsyntax/datawalk
Not really what you asked, but could serve the same purpose
definitely serves a similar usecase and looks like it could come in handy even if I get the pager thing working
@jesse.wertheim how about the tee
command? https://www.howtoforge.com/linux-tee-command/
you could tail the resulting file and fwd that to another process
@guillaume.carbonneau in this case it's more that I deal with some big data sets (and a few wide ones if processing from a spreadsheet rather than a DB), and am looking for a way to temporarily give up stdio control from the REPL to some other shell program, then switch back - kinda like psql
's behavior with opening what you've configured in the $PAGER
env var if the query output is too large. tee
could certainly play a factor if I also want it to output to a file ,but in this case it's more about the terminal UI
while looking into this I DID try out clojure 1.10's inspector
stuff though, which kinda serves a similar purpose, just graphically. pretty neat!
Is there a way to spec a map to contain a particular value? I’ve got this
(s/def ::canceled-result-code (s/with-gen #(= "1" %) #(s/gen #{"1"})))
(s/def ::approved-result-code (s/with-gen #(= "0" %) #(s/gen #{"0"})))
(s/def ::canceled-response
(s/merge
(s/map-of #{::ResultCode} ::canceled-result-code)
(s/or
:emv ::emv-response
:swipe ::swipe-response)))
(s/def ::approved-response
(s/merge
(s/map-of #{::ResultCode} ::approved-result-code)
(s/or
:emv ::emv-response
:swipe ::swipe-response)))
A minimal self contained example would be more helpful.
but it’s not able to generate data
the only difference between cancelled-response and approved is the value of the ResultCode
Because there isn't any difference b/w cancelled and approved response, why not just do
(s/def ::ResultCode #{"0" "1"})
(s/def ::emv-response (s/and int? even?))
(s/def ::swipe-response (s/and int? odd?))
(s/def ::response (s/keys :req [::ResultCode (or ::emv-response ::swipe-response)]))
; Generate some responses
(gen/sample (s/gen ::response))
I get this error
CompilerException clojure.lang.ExceptionInfo: Couldn't satisfy such-that predicate after 100 tries.
Can you conform any manually written example?
Can you show us the definition of ::ResultCode
?
Also FYI, Because sets implement clojure.lang.IFn
, you can define ::canceled-result-code
and ::approved-result-code
simply as,
(s/def ::canceled-result-code #{"1"})
(s/def ::approved-result-code #{"0"})
Also, I believe this is not an idiomatic use of map-of
.
as long as the data isn't nil or false yeah that's the ticket
A multi-spec
might be more appropriate here.
@jaihindh.reddy yeah i think you’re right
does multi-spec
work with generators?
@currentoor sorry for rambling there a bit. I think the error there was because s/merge
expects the args to be map-conforming specs and s/or
doesn't give you such a spec.
Yeah multi-spec works with generators just fine.
can you specify which “type” in the generators?
like i want a an approved-response instead of either
no worries, this is helpful
Here's what I came up with:
(s/def ::ResultCode #{"0" "1"})
(s/def ::emv-response (s/and int? even?))
(s/def ::swipe-response (s/and int? odd?))
(defmulti response ::ResultCode)
; These two method impls would be identical and contain (or ::emv-response ::swipe-response) Haven't written it like that to distinguish the difference b/w the two.
(defmethod response "0" [_] (s/keys :req [::ResultCode ::emv-response]))
(defmethod response "1" [_] (s/keys :req [::ResultCode ::swipe-response]))
(s/def ::response (s/multi-spec response ::ResultCode))
Now because response
is just a multi-method that ignores the argument and return the spec for a particular variant, to get a generator for approved result codes ("0" cases), all we need to do is to get at the method that we want.
(def approved-response-generator (s/gen ((get (methods response) "0") 42)))
We can then call it as usual.
(gen/sample approved-response-generator)
^ The 42
here is of no significance. We can pass anything there because it's ignored.
@currentoor Turns out we can specify it.
very kind of you to help like this
Anytime!