This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-13
Channels
- # announcements (1)
- # beginners (155)
- # calva (104)
- # cider (7)
- # clj-kondo (55)
- # cljdoc (2)
- # cljs-dev (19)
- # cljsrn (22)
- # clojure (230)
- # clojure-europe (1)
- # clojure-italy (15)
- # clojure-losangeles (8)
- # clojure-nl (11)
- # clojure-spec (20)
- # clojure-uk (30)
- # clojurescript (10)
- # code-reviews (32)
- # cursive (2)
- # data-science (6)
- # datascript (3)
- # datomic (141)
- # fulcro (1)
- # graphql (6)
- # jobs-discuss (19)
- # luminus (8)
- # off-topic (30)
- # pathom (2)
- # protorepl (8)
- # reagent (15)
- # reitit (3)
- # shadow-cljs (11)
- # tools-deps (1)
- # xtdb (8)
well first, you should avoid needing to do that
yeah that would be what I would suggest
@i Do you mean like this?
user=> (type (lazy-seq '(3)))
clojure.lang.LazySeq
user=>
The REPL by default tries to realize and print sequences.
@seancorfield i want to see what the macro lazy-seq expands into.
Ah, you want the source
function then...
user=> (source lazy-seq)
(defmacro lazy-seq
"Takes a body of expressions that returns an ISeq or nil, and yields
a Seqable object that will invoke the body only the first time seq
is called, and will cache the result and return it on all subsequent
seq calls. See also - realized?"
{:added "1.0"}
[& body]
(list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* [] body)))
nil
user=>
Or am I still not understanding you?
Or perhaps this?
user=> (macroexpand '(lazy-seq '(3)))
(new clojure.lang.LazySeq (fn* [] (quote (3))))
user=>
macroexpand
and macroexpand-1
need to be passed code so the form needs to be quoted.(they are functions so, in calls to them, Clojure will evaluate the arguments first)
You had (macroexpand-1 (lazy-seq '(3)))
with no quote on the form so Clojure evaluated (lazy-seq '(3))
first, then called macroexpand-1
on the result.
Hey there. I have a vec of vec that are integers and I need a to create a display
function that will map numbers to char or strings. Something to get [[0 1] [0 2]
to [["zero" "one"] ["zero" "two"]]
. I'm not sure how to start it though.
@hp_pedrors Is it for arbitrary numbers, or just for a small, known set of numbers?
How about a map then? {0 "zero", 1 "one", 2 "two",,,}
It's easy to invert a map, yes.
(zipmap (vals the-map) (keys the-map))
will produce an inverted map.
And if you want something for arbitrary numbers...
...drum roll...
(! 508)-> clj -Sdeps '{:deps {com.ibm.icu/icu4j {:mvn/version "64.2"}}}'
Clojure 1.10.1
user=> (import 'com.ibm.icu.text.RuleBasedNumberFormat 'com.ibm.icu.util.ULocale)
com.ibm.icu.util.ULocale
user=> (.format (RuleBasedNumberFormat. (ULocale. "En") RuleBasedNumberFormat/SPELLOUT) 1234.56)
"one thousand two hundred thirty-four point five six"
user=> (.format (RuleBasedNumberFormat. (ULocale. "Fr") RuleBasedNumberFormat/SPELLOUT) 1234.56)
"mille deux cent trente-quatre virgule cinq six"
user=>
You made me curious so I did a few searches 🙂
It took me a few minutes on Bing to locate a StackOverflow answer that included a library rather than reams of nasty Java code to do it half-baked.
Then I looked on Maven Central for the library coordinates and searched on Bing for the actual package names for the classes used in the SO post (why do people never include the dang import
statements in their Java code!!! 😠 )
Then it was pretty easy to fire up a clj
REPL with that dependency, pull in the classes and try their example...
I have my main work REPL open 24x7 for days at a time (sometimes weeks!), and then I'll run "scratch" REPLs as needed to experiment with new stuff I see talked about here, or to help people out.
My main work REPL is actually REBL, with a Socket REPL running (I use Atom/Chlorine for my editor). I love REBL!
Should private functions all be at the top and public all at the bottom of a ns, or should private functions associated with their public should be close together? Or does a guideline for that not exist?
Well, you can use declare
so you can put functions in any order...
...but my advice is to not worry too much about private functions -- they can still be called by other code!
One style is to group public and private together based on what they do. So "BADC". That's what I do.
I tend to organize functions in a namespace to be in general groups from lowest-level to highest-level, with comments to introduce each group of related functions.
I sometimes have private functions, but not very often.
As an example, our work code base has 3117 fns, 641 of which are private.
Other people though, just put all their private into a separate namespace, make them public and call the namespace like "namespace-impl".
In public OSS code, I'm more likely to either use private for stuff that isn't meant to be part of the documented API, or put all that in a .impl
namespace (as public functions).
And the third style I've seen, but I'd say it's the least common one is your BDAC one.
Because eventually, it forces you to use declare
, and the use of declare isn't very popular. Some people frown upon it.
My beef with not using private is it messes up my autocomplete 😋 in that then it lists way too many fns I don't care about
I have often found that I've eventually needed to make a private function public so I can reuse it outside the namespace -- so that's why I've mostly stopped using private functions.
Although there is a benefit to using private functions if you run Joker in lint mode -- it will flag any private functions that are not actually used!
Hum, generally, at that moment, I'd just make it public. Or if it's because it's actually a generic util or useful common util, I move it to a common utils namespace
Also, some linters don't support declare
, so I'd also probably say don't use it if you don't need it
When I eval (def a (atom 1))
, the symbol a
points to a var which contains an atom, which contains the Long 1 right?
Or does the symbol a
point directly to the atom
Because I remember Rich saying, you have reference types, which only ever point to values, and you have values.
And var pointing to an atom would break that.
Vars can "point to" atoms via evaluating an expression like (def a (atom 1))
.
It is possible after evaluating that to make a
point to something else, e.g. an immutable value like 1, or a different atom, or anything else, but most often in Clojure Vars "point at" the same thing for their entire lifetimes.
meaning, that is how people use Vars most commonly.
You could in Clojure create an atom that contains an atom that contains yet another atom, but there isn't much reason to do so.
I am not sure which thing that Rich said that you are referring to, but whatever he said, it sounds like he is describing what he recommends doing. He is not describing what Clojure strictly limits you to doing.
Sounds a bit like direct linking: https://clojure.org/reference/compilation#directlinking
Direct linking is about invocation, not values
If so, I don't think so. And I've never seen or heard that you could. But now I too am curious
No, that’s not a thing. The only thing similar is ^:const, but that’s for inlining compile time constants, which an atom is not
It depends on the library, I guess. Is it worth the extra work? Though, as a user, I do appreciate when a clojure library also works with clojuescript...
@seancorfield sorry, went to bed before you posted your last example on the .. and -> macros! Yes, it does work. Thanks again.
How do people normally test macros?
(deftest a-test
(testing "--> macro thread first plus __ placeholder option"
(is (=
(macroexpand '(--> 5 (+ 2) (- 4 __)))
'(let* [__ 5 __ (+ __ 2) __ (+ 2 __)] __)))))
is this a sane pattern?my macros usually looks like this
(defmacro my-foo [& args] (my-foo-fn* args &env))
And I test the function
Well that's neato, thanks
something more like
(testing "--> macro thread first plus __ placeholder option"
(is (= (--> 5 (+ 2) (- 4 __)) -3)))
Anyone know the difference between immutant.web.middleware/wrap-session
and the default ring.middleware.session/wrap-session
. The default luminus
template clearly prefers the immutant
one by putting the wrap-base
function like this
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
wrap-auth
wrap-flash
(wrap-session {:cookie-attrs {:http-only true}})
(wrap-defaults
(-> site-defaults
(assoc-in [:security :anti-forgery] false)
(dissoc :session)))
wrap-internal-error))
I want to learn Clojure by writing some games. Are there any libraries that you guys would recommend? Or is game programming in Clojure actually quite difficult?
I haven't written a game in Clojure and do not have any libraries to recommend, but I do know that multiple people over the last several years have published the source code of games they have worked on in Clojure, and/or written blog articles with some of the steps they followed.
This discussion from a couple of years ago has several library recommendations, for a "simple platformer" game the questioner is interested in writing. I suspect the library recommendations might be quite different depending upon the level of graphics and/or animation intensity you want to use.
there's a lib, camel-snake-kebab, usually used for making prettier renames of keys in json or xml data into keywords in maps
though often it reduces complexity to just use the original string
What's the difference between ^:internal
and ^:private
?
private actually does something concrete to the bytecode var created
internal is a random keyword as far as the compiler itself is concerned
is there a common technique to automatically add the repl and pprint namespaces to the namespace one is currently working on? without doing a require manually of those namespaces every time one restarts the repl
@lockdown- If your workflow is to work in an editor and eval code to the REPL (as it should be, rather than manually typing into the REPL), then your editor's integration should have the functionality you'd need from those namespaces "built in" as various key strokes...
@seancorfield how does those editors do it?
Depends on the editor. What are you using?
Ah, then your options may be pretty limited. CIDER/nREPL provides a much richer Emacs experience.
I use Atom/Chlorine and with my cursor on any symbol I can show docs, show source, jump to the definition, all with hot keys for Chlorine's built-in commands. I've added commands to inspect the symbol in REBL, inspect the namespace in REBL, etc. All my evals (form, top-level form, selection) also send the output to REBL so I can browse easily either via the tabular navigation or view data as pretty-printed EDN.
@dpsutton Good to know. I wasn't sure how primitive inf mode is. I haven't used it for many, many years.
i like the idea of it though. just formatting commands that any repl must understand
@lockdown- I know it's a commercial offering but I highly recommend Eric Normand's course on https://purelyfunctional.tv/courses/repl-driven-development-in-clojure/ as an excellent way to develop a really productive REPL-based workflow
@seancorfield chlorine and cider are too much magic for me now, was curious to see it all work, does that course uses just a plain repl?
It shows workflows based on Emacs/CIDER/nREPL and Cursive, but it's fairly generic and doesn't rely on many of their features.
It doesn't still showing "typing directly into the REPL" but only for exploratory stuff but it really does try to focus on eval-from-editor as the primary approach.
I'm all in favor of a simple toolchain -- it's why I use Chlorine and stick to a Socket REPL, rather than do anything with CIDER/nREPL -- but I like being able to do most stuff via hot keys from the editor, rather than typing shortcuts in the REPL.
yeah, I'm interested in automating all this stuff from my editor without going all the way to cider, had to much trouble with it
It's like nine hours I think. I really enjoyed it (and I recommend it to everyone because I'm a huge advocate of RDD).
Also, have you watched Stu Halloway's talks on this topic?
One is called Running With Scissors. An older one is called REPL-Driven Development, that he gave to the Chicago Clojure meetup last summer (I think).
I'm also no fan of CIDER based on past experience. Same goes for my colleague hiredman
(Kevin Downey). It's an amazing piece of tooling but I just had too many odd things happen with it (some were to do with breakage over upgrades, some of it was just Emacs config/tooling).
@lockdown- CIDER looks magic at first but once you are used to it, it works great.
There are only few commands which I use in CIDER.
one thing you can do is import all of this stuff to user.clj
and work from there. rather than being "in" whatever ns, just require it into the user ns and then you know you have source
, doc
, apropos
, and pretty print as you like
@lockdown- I use a shorthand macro in my user.clj that does all the "prep" I want for an active namespace
Also, eval (clojure.pprint/pp)
that will pretty-print the last thing printed (and works from any namespace).
and of course it's automatically valid in ns user in that case
@noisesmith understood my poor articulation of the problem
@noisesmith do you have it in a gist somewhere?
it's pretty idiosyncratic, let me check
https://gist.github.com/noisesmith/301713f0c7a4e3c98149ecf97556dcff it's crufty but not broken
and it doesn't even currently have the clojure.repl / clojure.pprint stuff :/ - easy to whip up oneself
@deleted-user Yes I have! I started while it was still being developed so I've seen some of the lessons multiple times as they've changed while Eric was developing the course.
I tend to watch Eric's stuff on 2x speed... that "Southern drawl", and all that 🙂
If you can arrange your screen to have the video in one half and your editor in the other, you can "play along" in your editor/REPL at the same time -- recommended!
He's an engineer, not a designer 🙂 But I know he'll appreciate feedback on how to improve the UI.