This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-07-25
Channels
- # aleph (2)
- # aws (2)
- # beginners (37)
- # boot (23)
- # cider (29)
- # clara (34)
- # cljs-dev (2)
- # cljsrn (17)
- # clojure (230)
- # clojure-dev (47)
- # clojure-italy (11)
- # clojure-nl (2)
- # clojure-poland (5)
- # clojure-russia (52)
- # clojure-sg (1)
- # clojure-spec (70)
- # clojure-uk (73)
- # clojurescript (31)
- # core-async (9)
- # cursive (15)
- # datomic (39)
- # events (1)
- # graphql (1)
- # lein-figwheel (2)
- # luminus (13)
- # off-topic (2)
- # onyx (29)
- # other-lisps (1)
- # parinfer (15)
- # pedestal (14)
- # re-frame (41)
- # reagent (24)
- # ring (4)
- # ring-swagger (12)
- # rum (1)
- # spacemacs (3)
- # specter (1)
- # test-check (13)
- # timbre (9)
- # unrepl (29)
- # vim (5)
@hmaurer re: tests, you may want to watch this: http://2017.clojurewest.org/full-stack-teleport-testing/
I have seen it. Mind-blowingly awesome. It’s on my todo-list to implement something similar 🙂
I essentially want to
(let [specs [:a :b]]
(apply clojure.spec.alpha/cat (interleave specs specs)))
what my options are?@U2PGHFU5U thanks, I just forgot about ~@ splicing. it's all good now
yep, I prefer eval personally for that stuff. a macro def will stay here in all its uselessness after you used it to generate your spec
I wanted a macro initially, because I have too many s/cat
s where I basically reuse spec names as dispatch keys
figured I'd try to just re-use spec names instead of coming up with throw-away names time and time again.
while we are on macro subject: how do grown ups validate macro's input (e.g. with spec)?
@misha s/conform
will give you the destructured version. if it’s ::s/invalid, then s/explain.
is there a way to get fn's arity? like
(arity filter)
;; => [1 2]
actually I am not even sure why I am asking this If function was defined with defn - (:arglists (meta #'filter))
Or why not (-> render .-prototype .-constructor .-length)
. We’re not barbarians after all.
for some reason, when writing code involving reduce, it's always: 1. how can I write this imperatively ? 2. then I reformulate it as reduce
@henrik: no concrete example, just that most of the time, I want to do:
(let [state (atom ...)]
(doseq ...))
then I end up "inverting" the doseq / modification to the @state atom in order to get my reduce code
@qqq There’s nothing inherently wrong with that, in my opinion. For me, it’s a quite common pattern that I pull out the transducers once I start noticing boilerplate and repeating patterns in the code.
@henrik: have you used Haskell? the haskell solution to this would be the 'state' monad, then an external sequence_
@qqq Unfortunately I haven’t used it beyond the tutorial on the home page (which is quite nice)
map
does seem to be easier to visualize than reduce
though. I think map
corresponds more to everyday patterns of life. You can imagine walking along a row of potted plants and watering each for example, getting a row of watered plants.
But what would be the reduce
version of that? Repot them in one large pot, one plant at a time?
But also, the order in which they were repotted would somehow matter. I don’t know, it’s not as straightforward.
@qqq in Haskell how would you solve the problem?
foldr
over a sequence?
(I'm just curious)
@chrisbroome : I would write the code "imperatively" with putState / getState, then put it on a do block + use sequence_ if there's a list
the point is that the code goes something like:
s <- getState
... do some processing ...
putState s'
but then the reduce somehow causes me to "invert" the state manipulationgenerally, than doseq. because that way you just delete a bunch of code and change some keywords. refactoring doseq and atom updates is annoying
nevertheless, it seems that in an otherwise clean language, there's this mismatch between "mental thought" and "how code has to be written"
mmmmmm my assumption is that that mismatch is just a result of spending so much time in imperative languages. I definitely find myself having to go through that interim step a lot less than I did 4 years ago when I moved ruby->clojure. could be wrong though
that’s foldl
and it’s provable that everything you can do via state manipulation you can do in a left fold / reduce, it’s just a different code pattern to do it
the state monad is a "purely functional statically typed" math trick around writing an imperative looking thing and still keeping it pure
yeah, I guess 99% of the problems I have with clojure is: it doesn't have haskell's type system 🙂
@qqq frege is haskell for the jvm, and it would even be usable except it is too hard to use interfaces or extend java types (because it really does implement haskell’s type system - which is better but also alien to the platform)
I would have totally used it for some things in my codebase but not being able to define or implement interfaces (not to mention concrete inheritence, which clojure taught me how to do without), it was a no go
Is there a way that others are using tools like eastwood
with files that contain namespaced keywords?
I don't recall any problems with namespaced keywords, but I seem to remember I had problems with namespaced maps. As these were limited to my test classes, I added these namespaces to the ignore list I think. Also, I think there were some fixes on the master branch that remain unreleased. A bit vague I realise, but if you're still stuck tomorrow (unlikely) then I'll check when I'm back in front of a computer...
Ah, to be more specific, I am using lein eastwood '{:add-linters [:unused-namespaces] :namespaces [:source-paths] :exclude-linters [:unlimited-use]}'
as my command, and I get an error for a namespaced spec (so you might be right that a namespaced keyword would not create problems, sorry!).
== Eastwood 0.2.4 Clojure 1.9.0-alpha17 JVM 1.8.0_121
Exception in thread "main" clojure.lang.ExceptionInfo: Invalid token: ::spec-ns/spec-name {:type :reader-exception}
When I use (:require [acme.spec-ns :as spec-ns]) ... (clojure.spec.alpha/validate ::spec-ns/spec-name) ...)
, this is the context I have using a namespaced spec in
@qqq I think their assumption is “just do it the way you would in haskell”
thing is clojure just has no need for a state monad, because if imperative code is what's appropriate there are mutable options
Well, cognitively, our problem solving is very pattern based. A problem occurs->go fetch the nearest solution from memory that approximately fits problem->apply to problem. Certain mismatch is bound to happen when encountering a somewhat different paradigm.
Personally, I find macros to be some of the most intractable marshlands of the language. The parser in my head doesn’t predict the output of a macro well at all.
@noisesmith I really liked the promise of Frege and spent quite a bit of time working with it -- I wrote a Leiningen plugin for it and put out some mixed Clojure / Frege code examples. But, ultimately, I just found it too frustrating to use and kept going back to Clojure... which kinda fits in with the love/hate relationship I've had with Haskell ever since it appeared (I always hoped Haskell would rule the world but it seemed like the team behind it tried very hard to make sure that didn't happen!).
yeah I think I might have first heard of frege from you - and if I could have just defined / implemented interfaces I could have used it for my project…
I just watched Prof Turner's talk about "Some History of Functional Programming Languages" from the Poland FP conference this year. Great to hear how everything came together (he was going to be my external examiner for my PhD thesis back in '86... if I'd actually completed it!).
We used Miranda at my university and I was familiar with ML and SASL and a bunch of the other FP languages that all merged into Haskell. I created my own (SURE), just like all the other FP researchers in England at the time! 🙂
I remember checking out CLEAN shortly after I got into software (by reading “tech yourself C++ in 21 days”)
in retrospect I’m amazed I got turned to such an interesting direction so early on
University of Surrey (Guildford).
SURE was Surrey University Recursive Evaluator 🙂
https://www.youtube.com/watch?v=QVwm9jlBTik&__s=csfyzpydsvfikkqz5bvw (for those who missed the link in Eric's http://PurelyFunctional.tv newsletter)
Hi! I have the following in a Datalog query:
'[:find ... :where [(wef-backend.app.identity/past-expiry? ?expiry)]]]
Due to how Datomic/Datalog works I must fully qualify the past-expiry? function, even though it is available in the namespace where I wrote this query
I tried syntax quoting on the query but that doesn’t work, as it fully qualifies the ?expiry, etc
variables too
@hmaurer you can use ` for this, and selectively use ~ for the symbols you want to namespace qualify
@noisesmith how so? I tried variations on your suggestion but didn’t manage to get it to work
peregrine.circle=> `[:find ... :where [identity ~'?foo]]
[:find ... :where [clojure.core/identity ?foo]]
I just picked a random thing with identity in the name, but I hope it translates
I guess I should have explicitly mentioned the ~'
idiom to prevent namespacing
is there a way to do the opposite? selectively pick the symbols I want to namespace qualify
that’s harder
this is close, but no cigar
peregrine.circle=> '[:find ... :where [`identity ?foo]]
[:find ... :where [(quote clojure.core/identity) ?foo]]
~ doesn’t make sense outside `
it’s inside the ` at the beginning of the vector
right, but why does swapping out the use of syntax quoting vs normal quoting makes it different in use?
because ~ is only valid in syntax quote
it’s a special operation that is only defined in that context
using it outside throws
java.lang.IllegalStateException: Attempting to call unbound fn: #'clojure.core/unquote
right, it exapands to unquote, that is undefined outside `
this is all stuff implemented in the java code of the reader
it isn’t built on the normal machinery, it’s the basis for it
syntax-quote ` is special, and it handles unquote
right, it’s a parser machinery basically
we’re at the point in this convo where I’d probably have to read more code to answer more questions though
like whether there’s an actual unquote method somewhere in Compiler.java or if it’s entirely a figment of syntax-quote
For now I think I am contempt with the answer that clojure.core/unquote is not a function, but something that has a special interpretation within a syntax quote
there’s this, but I am not totally sure what it means - UNQUOTE used to be defined as a special symbol but now it is commented out https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L70
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L986-L990
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L1040-L1044
the tl;dr is that when the compiler sees ~foo
it expands into (clojure.core/unquote foo)
@bronsa ah, so if it’s an unquote form it simply gets rid of the “unquote” and “quote” bits at reading time?
but because of splicing, it has to wrap every subform that is unquoted in a list & concat them all
the impl is quite more complex because it has to deal with maps/vectors/sets other than just lists
has anyone written about how to organize specs when they don’t perfectly map to namespaces etc?
I’d be interested to see a well reasoned pitch justifying the practice
your data domain doesn’t match your namespace organization?
it seems like people are really tied to namespaces on keywords matching the namespaces code is organized in to
The only time I ever use a code namespace name on a keyword is when I am sure it is temporary and will change
well lets say I have some type of domain object. Most functions operating on that are in some namespace that might contain multiple spec’d domain objects. To define specs for these objects I’d have to do something like (s/def ::my-object-name string?)
does that make sense?
never use ::
and instead of tying to the namespace the code is currently in, use a namespace like :my-org.project/whatever
ok yeah, that seems like a sensible argument
right... I'm also more and more inclined to not use ::
, but using data domain logic.
your specs are like a database schema, imagine if in tables you named columns after the code that is currently accessing it, terrible
@hiredman another option is to have namespaces dedicated to your specs, I've being doing that and I quite like it, you can have a namespace like your-org.specs
and inside of that you create the namespaces with your data definitions, by doing that the ::
gets very convenient, also you ensure very long namespaces so you have a more strong uniqueness sense
Yeah, but putting all specs in there isn't much fun either...
I've been splitting the specs and where to put them and how to name them depending on the purpose.
here's something easy to do with state monad but non-obvious to me how to do with reduce: I have a expression tree. I want to compile it to Three-Address-Code, i.e. a list of statements where each statement is (set! a (op b c)).
how would you do it with the state monad? I think the trickyness here is more traversing trees than building up state
with a state monad, you just keep an int counter, and increment it as you traverse the nodes of the tree
I'm writing a blog post on REPLs, can anyone recommend a short video demonstrating the Clojure REPL?
@hmaurer 'what makes a good REPL?' - what value do REPLs bring, what features make for good REPL, what programming language features enable them
@U064X3EF3 a bit too long :) I need a 2-minutes thing
@qqq clojure's reduce isn't really for folding over trees. it only folds over seqs. so you'll need to write your own fold over a tree or flatten the tree first
https://gist.github.com/hiredman/2b2707d74ad2ff0b2f941b965f7dd97f#file-ref-clj-L3-L13 is an example of a custom reduce implementation over a tree using cps
I don't know what your expression tree is like, but if you can transform it in to something like anf generating three address code will be much easier
Hi all, I´m just starting with clojure, currently I am reading "The joy of clojure", and while trying to implement an example from the book, I am getting the following error on REPL:
user=> (def frame (java.awt.Frame.))
CompilerException java.lang.reflect.InvocationTargetException, compiling:(form-init6212165196188451204.clj:1:1)
user=> frame
#object[clojure.lang.Var$Unbound 0x4aabdabc "Unbound: #'user/frame"]
I was wondering if someone could point me in the right direction?also, the most likely cause of that error for that code is using a headless JVM
which won’t include awt
@heucles what does (resolve 'java.awt.Frame)
say?
(http://matt.might.net/articles/a-normalization/ is a good write up on anf)
hey @noisesmith I think you got it right, I´m in another environment right now. But I recall a message mentioning something about "Headless", if that is the case, do you know how can I solve it?
by installing a jvm that’s meant for doing desktop /gui stuff
but that shouldn’t be urgent for learning clojure (though playing with windows and widgets can be nifty)
typically on eg. a debian system, you can pick different jvms and decide which is default, and the one they pick for you if you aren’t too bothered to customize doesn’t come with the desktop and graphics stuff just to keep default installs smaller
but the process of getting the right jvm installed for the features you want will vary based on your OS
@noisesmith I thing I´ve got it, I´ll try to fix it later and I´ll let you know, but anyway I will follow your advice and wont let it get to much in the way of my progress, thank you very much!
I'm trying to wrap my head around core.async/pipeline-async
, and it seems to be running more parallel tasks than I'm requesting: https://gist.github.com/lynaghk/01aaa39bedcd2d37032dba3b68d9f94f
Is the "parallelism n" in the docstring more of a suggestion than a hard limit? Even when setting n=1, I'm getting three async tasks running at the same time.
pipeline-async is really weird, the other two pipeline variants are much easier to work with and much more likely to end up something that works like you expect
@hiredman Thanks for the link! I have to run this in cljs, so pipeline-async is my only option.
Off-by-two isn't going to be a dealbreaker for me, I just wanted to make sure my understanding was sound.
Looks like the async.clj and async.cljs implementations are the same, so presumably cljs would have the same issue.
anyone know why running lein run
might overwrite my .lein-env
file?
https://github.com/weavejester/environ/blob/master/lein-environ/src/lein_environ/plugin.clj
it looks like .lein-env is a generated cache that environ owns and you shouldn't be modifying
I was (with much rejoicing) teaching a couple of colleagues Clojure today, and one of them asked a question that stumped me. Why is there no delete
function for vectors? As in, to drop an element at an index out of the vector and move the succeeding elements backwards by an index to fill the hole?
because that's a very expensive operation, so you should stop and think rather than just seeing an 'easy' core op that does it
OK, fair enough. I wondered if that was why but wasn't sure.
@hiredman is correct, @josh_tackett. The .lein-env
file is for internal use, and shouldn’t be modified manually. It also mentions that at the top of the README.