This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-13
Channels
- # bangalore-clj (5)
- # beginners (94)
- # boot (145)
- # cljs-dev (4)
- # cljsjs (79)
- # cljsrn (18)
- # clojure (343)
- # clojure-dev (21)
- # clojure-dusseldorf (6)
- # clojure-india (1)
- # clojure-italy (2)
- # clojure-nl (4)
- # clojure-russia (62)
- # clojure-sanfrancisco (1)
- # clojure-spec (109)
- # clojure-taiwan (1)
- # clojure-uk (103)
- # clojurescript (102)
- # code-reviews (30)
- # component (1)
- # cursive (39)
- # datascript (7)
- # datomic (68)
- # emacs (11)
- # figwheel (1)
- # gorilla (1)
- # hoplon (234)
- # off-topic (46)
- # om (52)
- # onyx (32)
- # planck (9)
- # proton (4)
- # protorepl (5)
- # random (1)
- # re-frame (36)
- # ring (18)
- # ring-swagger (1)
- # specter (6)
- # untangled (3)
- # vim (56)
any ideas of making something like this more elegant:
(defn fancy-fn [foo bar]
(when foo (environ :env {:foo foo}))
(when bar (environ :env {:bar bar}))
(do-something foo bar))
does environ have a side effect @ag ? You're throwing away the intermediate result of (when foo (environ :env {:foo foo}))
if i'm rolling blind -- sounds like three side-effects -- I'd split into three functions... If I'm rolling blind.
no I mean side-effects aside, how can this pattern be improved? Maybe pattern matching or something like that?
maybe this is a crude approach, but if you have a lot of foos and bars, you could put them in a vector and iterate over that vector, performing your side effect on each one
my 2 cents: it sounds like @ag is looking for a macro
(defn ^:private twoflog
"Finds the largest power-of-two k < n, i.e. such that k < n <= 2k."
[n]
(loop [k 1]
(let [next (* 2 k)]
(if (>= next n)
k (recur next)))))
(->> 1 (iterate (partial * 2)) (take-while (fn [k] (< k n))) last)
What’s the preferred implementation here? I kind of like how declarative the latter is, but....hi what is the best way to walk through two sequences comparing each positional elements?
hi all. Is there a library to (compare {:tempid 2 :val "hi"} {:tempid _ :val "hi"})
in tests and that compares by form and yields true in this case?
I suspect core.match
will get you some part of the way there...?
boot.user=> (match [{:tempid 2 :val "hi"}] [{:tempid _ :val "hi"}] true :else false)
true
Yup, or that. I always forget about that one.
@seancorfield , @hiredman thanks!
Any recommendation for a templating library for clojure? I want to generate an xml with dynamic data. Should I go with stringtemplate4 (used by antlr4) or something like selmer?
Selmer is pretty good & will work with with anything (not tied to any output format particularly)
Not familiar with stringtemplate4, but based on what I see from a quick look at the docs, that seems a fair assessment.
http://yada.juxt.pro currently gives 502 error
https://juxt.pro/yada/index.html works for me.
How do you run expectations from a repl? (https://clojure-expectations.github.io/index.html)
On http://clojure.org the reference about the reader says that
Symbols beginning or ending with ':' are reserved by Clojure. A symbol can contain one or more non-repeating ':'s.
, is there symbols that actually begin with a colon and if so how does the reader differentiate them from a keyword ?@yenda I think that what is being suggested is that a symbol (any combination of characters, more or less) starting with a :
is actually a keyword.
well, "should be" is more like it, there are always differences between what's what at read-time vs runtime, it's full of oddities
hi, i have a namespace issue…
(ns server.core
(require [datomic.api :as d])
(:use ring.adapter.jetty)
(:gen-class))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!")
(defn handler [request]
{:status 200
:headers {"Content-Type" "text/html"}
:body (d/q '[:find [(pull ?id [* {:bracket/parts [{:part.spec/part [*]}]}]) ...]
:where [?id :bracket/name]
(d/db (d/connect uri))])})
(run-jetty handler {:port 8000}))
after lein uberjar and running and curling i get back java.lang.RuntimeException: No such namespace: d, compiling:(NO_SOURCE_PATH:18:33)
any reason why you cant do this?
(let [{:keys [some-number another]
:or {some-number another}} {:some-number 5
:another 10}])
(i get an unable to resolve symbol ‘another’ in this context)
just interested as to why
@biscuitpants because it's a wrong match in the or
part. It should be smth like :or {:some-number 1 :another 42}
@isaac_cambron Sorry this is so late, just saw your exchange earlier. Notice the (def f #'foo) vs (def f foo).
@isaac_cambron I think I learned this from https://www.infoq.com/presentations/What-Sucks-about-Clojure-and-Why-You-ll-Love-It-Anyway
@jonsmock 👍 thanks
I think Chas explains the trade-off in the video. I assume you're not doing anything high-performance (b/c how often are we really?) but if you are, I think there's a perf trade-off here
oh really? thank you @igrishaev !
@biscuitpants sorry w/o colons: :or {some-number 1 another 42}
I'm having some issues with logging. I'm using clj-log, and my logs are all showing as coming from the user
namespace. I've put together a minimal reproducible example here, which includes the output I'm seeing in the README: https://github.com/lyndsysimon/clj-broken-logging
It seems like clojure.tools.logging
is doing some magic somewhere to resolve the "actual" namespace, even when *ns*
is user
. clj-log isn't doing that.
@lyndsysimon AFAIK, no magic here: https://github.com/clojure/tools.logging/blob/528d7cf16fa0bfd0eda249453b095933de8bb30f/src/main/clojure/clojure/tools/logging.clj#L90
ah, scratch my message, you were talking about clj-log, not a bug in clojure.tools.logging
looks like clj-log is using runtime value of *ns*
[1]
that is wrong, they should use macro-expansion-time value of *ns*
[1] https://github.com/yogthos/clj-log/blob/master/src/clj_log/core.clj#L33
I dug through that code, but my Clojure ability isn't yet up to the task of solving this.
you can easily test that they use runtime value, by binding *ns*
to an arbitrary value before calling clj-log.core/log
, it will happily print it as current namespace
@lyndsysimon the problem is that c.t.l uses a macro for log
while clj-log uses a function
Gotchya. OK, that should be enough information to start me down the right path.
clojure.tools.logging/log
will use your proper namespace, because namespace name was baked-in when the log
macro was expanded
Looks like it's time for me to learn to write a macro.
this is my logging APIs need to be macros if they're going to capture the namespace
That function looks small enough to cut my teeth on, too. Awesome.
In all seriousness, it's past time that I dig into macros. I know what they do and when they should be used, I've just purposefully avoided learning the syntax to this point.
`~@ and friends are not "macro syntax", it's just reader syntax for expanding quoted data structures
bronsa: Well, there is syntax that is only used with writing marcos. If you're referring to homoiconicity, I'm already in love with it 🙂
OK, cool. I'll correct my misconception.
i’m sure there’s an awesome reason for conj behaviour re lists vs vectors. anyone can explain what it is ? 🙂
I assume Clojure uses forward-linked lists? If so, adding to the head will require modifying one object (the one you're adding). Adding to the tail requires modifying two (the one you're adding and the one that was last in the list).
"modifying" is a simplification, obviously 🙂
Clojure uses single linked lists
@lyndsysimon try this hack https://gist.github.com/darwin/930123e5237bd3eb2581894510c447e6
@lyndsysimon so you can only add to the head of lists
@lyndsysimon you need a reference to the tail to add to it
Vectors allow you to append at the end
conj is not defined to work on sequences, but as a polymorphic operation on collections
meaning it will insert the element in a way that makes sense for the collection, in the most efficient place for that collection
you’re looking at a function and unless you know its call chain you don’t know the outcome. that’s poor design
the intended consequence is that you have to reason about what data structure is the best to use in your code
it adds something to a collection
notice that conj also works with sets (adds the item to the set) and with hashmaps if val = [k v] in which case it adds a new key/value
I'm coming from Python, mostly. One of the things I look for in evaluating potential Python devs is how they choose between tuples, lists, and sets. Devs who understand Python's type system very well tend to use lists only if they are forced to. This seems similar.
in clojurescript, does that fall back to the overloaded plus and do appends and string coercing?
that's a meaningless question, conj is not a parallel to cons. they're different operations. in clojure both conj and cons exist
they just work on different abstraction levels. conj works on collections, cons on sequences
but generally if you need to append to the tail, it's a sign you don't want to use a singly linked list
@darwin - I've got my logging problem half fixed 🙂
re the conj question above: http://clojure.org/guides/faq#conj
and going meta, if you see a “frequently asked question”, check the faq first. if it’s not there, file an issue or send a PR to https://github.com/clojure/clojure-site - I would love for these kinds of questions to be easily redirectable to a central edited answer
Anybody having any problems doing Clojure on Mac OS Sierra?
… well, it won’t write my code for me, yet. i still have to do that bit myself 🙂
@pupeno are you seeing problems and want to see if anyone else sees the same problems, or are you just double-checking before upgrading?
@jrheard double checking before upgrading.
I’m getting older… I’m letting other people suffer the first-mover pains 😉
Any idea why the clojure jar does not have history enabled under bash (Ubuntu)? Same jar works fine in Windows.
what does that mean?
if you are seeing it on windows then that functionality is coming from somewhere else
is there a way to get pprint to print tempids as tagged literals instead of like {:part :db.part/user :idx -123}
?
@darwin 3.5 hours later, I can write macros.
https://github.com/lyndsysimon/clj-log/commit/27882b3642c23d8cd3d678352516e76cec04d2d1
the destructure mapping is symbol to index instead of symbol to keyword (when destructuring maps)
@lyndsysimon congrats, that was fast 🙂 looks good to me, but make-message bakes in time at macro-expansion time, that is not what you want
Hmm... I see that that happens, but I'm not seeing the negative impact. Why don't I want that?
well, I would expect log data to contain :time
representing runtime time the log was logged, not time when the code was compiled
Ahhhh
Gotchya. I should handle it in log
like I do it in logf
Unquote the function, not the form where it's called.
btw. make-message or log-message in logf are not necessary, it is the default behaviour of syntax-quote to provide fully qualified namespace to symbols which are not fully qualified
Hmm. OK. I was getting an error that the symbols were undefined in the current namespace, but that was much earlier and who knows how much I've changed and learned since then.
java.lang.IllegalStateException: var: #'clj-log.core/make-message is not public
Good deal 🙂
I'm happy to learn.
I would call make-message and ex-log at compile time and merge them at compile time and then simply emit resulting static map, with :time to be emitted as having value (new Date)
and try to do as much work as possible at compile-time, but be careful not to emit huge amounts of code, it is always a tradeoff, either you want to optimize for speed (e.g. logging in a tight loop) or code size (e.g. logging all over the place and you don’t want to balloon your code size much)
coming from Ruby, I actually have a long-standing question in my 2 years of learning clojure. how does one debug clojure code? is there something compared to binding.pry repl of ruby? I use vim, and maybe that's why I have this problem. I heard that Cursive has a full-blown breakpoints/local state inspection/modification and other IDE debugging features I remember from C# IDE.
I use println, and logs, same as I use with any other programming language 🙂, the main difference with clojure there is the repl is more first class, with other languages either they don't have a repl, or it is second class to running code from a file
so there is nothing like cd-cause to jump to current exception to investigate program state?
https://github.com/GeorgeJahad/debug-repl was maybe the first, but it may not work any more
it sounds like different tool chains have different kinds of mechanism like that, cider and cursive
but I've been happy with printlns and logging, and those work everywhere, so I cannot speak to them
https://github.com/gfredericks/debug-repl looks like an updated version of debug repl to work with nrepl, but nrepl is a lower level communications protocol, so you'll need a client and the client will have to support it too
@leov does Rails let you have a live REPL into a running application so you can modify it on the fly?
clojure compiles to jvm bytecode and includes debugging information, so in theory you can use any java debugger with it
@seancorfield, yes it does
https://github.com/m0smith/cljdb people have built stuff using jdb (sort of like gdb for java)
inside Rails process - on breakpoints only. Inside live system - via database mutations (by spinning off another console process and doing changes to external services connected to your app. But more often it's excercising problematic code so that you can drop into exception context)
@leov If you have a REPL running in a Clojure app, it’s a full REPL: let’s you execute any code and redefine functions on the fly — so the debugging experience tends to be very different. You can enable and disable tracing, add and remove println / logging, fix bugs etc.
I think the REPL is why we’ve not seen “traditional” debugging tools catch on with Clojure: we have something richer.
yes, but my usual and most powerful debugging procedure (worked 80% of the time, though, due to some recent ruby glitches) was just to run problematic code and then get the exception, and run cd-cause to drop into the context of where it happened. I guess it is almost like 'break on exception' in IDE
my observation on debuggers is people that want them really really want them, and people that don't, don't
in clojure with REPL I am doing more of a 'scientific method' (that is, guessing). I cannot put a breakpoint, slightly change state, and re-run a snippet. Instead, I'm changing the snippet in vim, so that the scaffolding paragraph/snippet is above or below the problematic code, rerun it, and the whole thing, surprisingly, comes slower for me.
I asked George to share the debugger kool-aid with me at the first conj, because I wanted to know why he cared so much about them, but I think he thought I may have been winding him up
i think it would absolutely be useful to have a pry-like experience w/ clojure apps. the benefit that most people (including me) are missing now: events triggered by exercising the app out-of-band (e.g. web requests). a debugger solves some of that, but afaik doesn't get you as far as dropping into a full REPL on these out-of-band events. [i'd love such a tool, but not so much that i'm going to write it.]
the CIDER debugger will let you break on fns and get a debugger. I’ve successfully debugged asyc web requests that way.
currently, because of REPL availability and debugging, I have these scaffolding 'test' snippets near half of my important functions
@trptcolin, yes, your description is more accurate. the problem is in out of band events, I guess
ok, I'll try to dig into tracing. Also I need to look into Cursive whether it has 'break on exception' thing
@leov I'm interested in discovering what Ruby/Rails has to offer in terms of interactive development. Do you have some good resources (videos, blog posts...) to share about this?
my understanding is, at least as of summer this year, mri does not execute ruby code in parallel
@leov there was a nice presentation at the Conj about Sayid, a tracing/debugging tool
The flow I'm trying to improve is essentially: transform -> validate -> handle errors if any -> transform some more -> repeat
usually, in cases where something like either or maybe seems appropriate, I tend to use a one off over pulling in algo.monads, but generally I stick to lists (monad wise) for which for
is enough for me
a one off might be returning a vector, the first element being a result, or the second an error
Can anyone recommend an article on better understanding why interning keywords "provide very fast equality tests -- http://clojure.org” and if the interning process is different from symbols.
IMO, monads are mostly a side-effect of dogmatically pure functional languages. You can use a monad or you can use a little bit of mutability. Often the latter is more idiomatic in Clojure.
using algo.monads is just fine, but if you are asking if that is idiomatic, and if idiomatic means "if you surveyed clojure code what would you see", then algo.monads is not
@kingoftheknoll keywords in Clojure are identical?
if the names are the same. Not so with symbols.
identical? checks can be compiled down to a pointer comparison, where symbols must be compared by calling .equals (or .equiv) on the symbol.
As so fast equality checks keyword to keyword. I was thinking that meant if you had two maps with the same keywords that would be faster. But I know that maps do equality on value
@tbaldridge ah that makes sense.
clojurescript (atleast last I checked) doesn't always have identical? keywords, so if you are using clojurescript watch out for that
and hashmaps have special cases for keywords, if you look up something via a keyword it will use identical?
I've heard that before, @tbaldridge, and I generally agree. But I'm not sure how mutability would help me in this case.
So you’re saying the lookup is faster because key in the map can be found/resolved faster
so it was a macro that took a body, a "success" message to put, and a error message if there was an error
so each step, if no errors, performed its action in a try/catch and put the error if that was caught
I might have my transform function return a list of items instead of a single item, and just return an empty list on error
i actually destructured the data going through so it was an anaphoric macro with [{:keys [data success errors :as payload}]
as the signature for everything
Where the validators call the next handler with their argument if they don't find any errors.
@leov Cursive does indeed have break on exception, the most useful breakpoint IMO. I did a talk at Clojure/West about the debugger last year, which is mostly a demo but also talks about the limitations of debugging Clojure: https://www.youtube.com/watch?v=ql77RwhcCK0
@zane, I have to ask...thought of using spec?
it does a lot of of this error stuff
I did a prototype of something like that, your predicates can refer to dynamic vars, or DB connections.
One of the validation steps is to conform the input to a generic spec (parsing), then a second one is to validate that parsed/conformed value against the schema.
I'd be tempted to generate a spec from the datomic schema. Seems like it'd be a bit cleaner than writing a second validation framework
@hiredman: test.check also has 3 or 4 adhoc monads
The monad monad
@gfredericks I've been interested in that, do you have a good paper on the design of test.check?
I'm wondering if monads are essential to the design of property based checking or if there's a better way. Since they do add a lot of complexity and mental overhead in a language like Clojure
There's eval (and yes I'm serious)
It also feels like there's maybe value in differentiating between syntax errors and non.
Seriously though, I'd love to hear an argument against eval in this context.
@tbaldridge the quick answer is that test.check is monadic to the extent it was ported from haskell
I haven't really thought about how you might design it from scratch
back when I was paying more attention to cljs performance, I tried to think of a way to do something transduceresque to the shrink trees so they wouldn't create so many intermediate collections, but couldn't make it work
now that I think about it, since it's a tree, I wonder if zippers would help...that might not make any sense
well yeah, that's been my thinking as well
which part
I was able to remove monads from miniKanren, so I thought it might be possible here as well
you got some benefit from doing that?
it's simpler code
what did you replace them with?
transducers, so rule becomes keep, conjunctions become comp, etc.
the difficulty I had with sprinkling transducers on the shrink tree was that it's two-dimensional
and maintaining arbitrary navigation is valuable