@noisesmith Reminds me of something I read once about Richard Feynman -- he reinvented / rediscovered parts of trigonometry on his own, and had a period of adjustment when he found out what notation others used for it in math classes.
haha, right - as programmers we do a lot of off-roading but sometimes its useful to be able to adopt the official traffic rules and get on the freeway
and the more math I learn (mostly set theory, linear algebra, group theory, category theory so far), the more I see things I used informally / in a very basic way, reformatted to be simpler and more reusable
not claiming to be anything like a Feynman, I'm just fiddling with some numbers
I was impressed that he rediscovered parts of trigonometry on his own before learning it from others. Pretty cool.
he would have been a polymath if he was born two centuries sooner, he was just that kind of thinker
Given this Data structure How could I append to allbooks? (def data-base {:nameHere {:allBooks ["harry potter" "twilight" "hunger games" "hunger games 2" "hunger games 3"]} :horror ["hunger games" "hunger games 2" "hunger games 3"] :love ["twilight"] :count 3}) this works (vector (get-in data-base [:nameHere :allBooks]) "yeash") but not this (update-in data-base [:nameHere :allBooks] (vector (get-in data-base [:nameHere :allBooks]) "worked"))
update-in takes a function which will be given the current value
(update-in
data-base
[:nameHere :allBooks]
conj
"worked")
Thank you so much, it was driving me kinda nuts. I tried something similar, but conj was in parenthesis.
Ya, when something takes a function as argument, you need to pass it without parenthesis
Or you need to pass in a Lambda, so sometimes you'll see:
(update-in
data-base
[:nameHere :allBooks]
#(conj % "worked"))
Yeah, that looks a lot clearer.
Hi everyone, in Programming Clojure in the Snake game part there is this section
" (defn head-overlaps-body? [{[head & body] :body}]
(contains? (set body) head))
(def lose? head-overlaps-body?)
Test lose? against overlapping and nonoverlapping snake bodies:
(lose? {:body [[1 1] [1 2] [1 3]]})
-> false
(lose? {:body [[1 1] [1 2] [1 1]]})
-> true"
I have a few questions
1. Why is lose? a def
but it is called like a function?
2. Coming from a Ruby background, it seems like lose?
is a function calling another function but its definition doesn’t seem to accept any arguments, how does it know it can accept arguments and also pass it to heads-overlaps-body?
(which also doesn’t seem to be accepting any arguments in lose?
lose?
is not a function calling another function, it's just a variable that points to head-overlaps-body?
(defn foo [] 42)
is roughly syntag sugar over (def foo (fn [] 42))
, maybe that helps you understand the second line in your example
clojure.core/defn
[name doc-string? attr-map? [params*] prepost-map? body]
[name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?]
Macro
Added in 1.0
Same as (def name (fn [params* ] exprs*)) or (def
name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
to the var metadata. prepost-map defines a map with optional keys
:pre and :post that contain collections of pre or post conditions.
Thanks for your answer, I understand the answer to the first question. But for the second question, I’m still not sure how it works. How does the arguments I passed to lose?
get passed to head-overlaps-body?
As @dromar56 pointed out, lose?
is a var, essentially an alias for head-overlaps-body?
. Calling lose?
with arguments is functionally equivalent of calling head-overlaps-body?
with them, but the name makes the idea more explicit here.
As everybody pointed out, it is just an alias for the same exact function (effectively giving one function two names which can be used to invoke/call the function). In 7 years of doing Clojure I have never really done such a thing, so it is quite unusual style IMO.
I’m not sure I have enough experience to comment about the style, I found it in the Programming Clojure book.
Technically, you can give the function any number of “aliases” like:
(def my-name-1 head-overlaps-body?)
(def my-name-2 head-overlaps-body?)
Programming Clojure is a good book, perhaps for this small-scale example it’s OK. In a real project perhaps I would consider just naming the function lose? and putting a comment like:
(defn lose?
"We lose the game when the head overlaps the body."
[{[head & body] :body}]
(contains? (set body) head))
Yeah that makes sense, thanks for the tip! :thumbsup:
You’re welcome 🙂
could you recommend a simple online REPL? Preferably one which allows to edit and run multiline scripts
clj/cljs - doesn't matter
https://www.maria.cloud/ like this?
probably, but I still don't understand how to run a script there, only found the shape drawing tutorial
oh, it's like Jupyter notebook and I need to press Enter to create an actual code block
Here's a new one that popped up recently
It'll allow you to type in scripts and execute.
there is another one, but it is not “online” you have to manage it itself - http://gorilla-repl.org/start.html
And of course, there is <https://repl.it/languages/clojure>
, although you'll need to sign up.
I recently found this new one: https://paiza.io/projects/9-Daq1Zrz1s-al0nqE0YUA?language=clojure
Hello, I am trying to test that if there is an invalid input there will be an ExceptionInfo
using thrown-with-msg?``
let’s say
(defn validate-input [input]
(if true
(throw (ex-info "invalid input" {:input input}))
nil))
(deftest input-validation
(testing "when validating"
(is (thrown-with-msg? ExceptionInfo #"invalid input"
(validate-input "input"))))
tried to run gorilla-repl and it doesn't work
but it’s failing
it’s saying that ex-info returns an error dictionary instead of actual error
so what would be a better test for this scenario?
that code looks right to me (except input-validation is missing an end paren)
are you sure your repl state matches your code?
ok more context
expected: (thrown-with-msg? ExceptionInfo #"invalid input" (convert "dsfds"))
actual: #error {
:cause "It is possible to parse only numbers from 0 to 1000"
:data {:input "dsfds"}
:via
[{:type clojure.lang.ExceptionInfo
:message "invalid input"
:data {:input "dsfds"}
:at [numerals_kata.core$validate_input invokeStatic "core.clj" 13]}]
:trace [[ .... ]]}
this is what the test returns 🙂
yes, the bracket is there in the original file. I just took one test out of deftest, that’s why it was missing here.
for what it's worth, your first code sample runs fine for me, and passes (after adding a closing paren, that is).
issue is: #"invalid input"
does not match "It is possible to parse only numbers from 0 to 1000"
Looking at that error there.
ha! it does work!!!!
yes, I was checking for different strings!
thank you all!
I just spent 20 minutes looking at a string that was almost right….
A lot of programming experience is these kinds of 20-minute episodes, that in future lead you to ask different questions and check different things when things are going wrong, and the next time it will probably be less than 20 minutes 🙂
@jaihindhreddy by the way, hello to this amazing mentor from exercism!
👋
Is there a function similar to transduce or reduce that calls the completing 1-arity of a reducing step function?
Something like (rf (reduce rf source-seq))
I've been solving by doing this but it feels wrong:
(transduce (map identity) rf source-seq)
from here: https://guide.clojure.style/#body-indentation why is this good?
(when something
(something-else))
while this is bad?
(filter even?
(range 1 10))
is it simply because the (something-else)
part is the body arg of the when
macro?that guide is entirely subjective and just some people's opinions. I happen to agree with this one though. the when
establishes a kind of context that (something-else)
is executed in. for filter
the args are of equal importance so I like them to be aligned.
when
is macro, filter
is function
right, but even this style guide uses this language: “Vertically align function (macro) arguments spanning multiple lines.”
it seems to elide them, at least in my reading
some people do like that style of arguments staying to the left as far as possible as it can prevent lines from getting too long. I much prefer the alignment as it makes visually scanning the forms easier but sometimes it does get tedious in line length
vertically align both, but macros get 2 spaces
(when true
(foo)
(bar))
;; horrendous
(when true
(foo)
(bar))
with if
?
also what do people think of aligning associative forms (maps)? I almost never see it. When looking at the fulcro tutorials I saw Tony Kay doing it and I immediately copied it.
love to read it hate to see a diff where a single line changes the entire map. same with binding forms in let. those are the major arguments on each side. where you land on that seesaw is pretty personal and not standardized from what i can tell
The identity transducer is just identity, you don't need to map it
relevant: https://metaredux.com/posts/2020/12/06/semantic-clojure-formatting.html
@jeffrey.wayne.evans so the answer is "the 2nd is bad because looking at it does not convey it's a fn call (as opposed to a macro, which it isn't)"
thanks. I imagine this becomes automatic over time, but I also presume some editors are aware of this magic and can actually follow it
I mean, source
and doc
are always at the ready
Don't align. Better git history, and more compact code (at the expense of visual rhythm). Same for let bindings.
in cursive control-q or f1 are amazing. a nice little popup of the source along with clojure-doc examples
wait, you use Cursive too? 😆
I think Go did it right. They only have 1 way to format things, no configuration. The only sensible alternative is to individually format during development, while the checked in code is formatted by the “one true way” (or not at all). I don’t see the cost-benefit there though.
hell, even mouseover seems to get you that
Ou right! I get it, you get formatting commits this way obviously
I dislike those too
i do every now and then. i have a paid license because its really great software. If i did more interop i might look at switching or having it more at hand. its interop story is top notch
emacs can't compete with cursive's and intellij's java knowledge
"with clojure-doc examples" you say?
> hell, even mouseover seems to get you that what's a mouse?
yup. really slick. CIDER implemented it after colin did i believe because its so handy
example:
there's also a quick peek for source which is super super nice but i forgot the key binding at the moment
I formatting lisps is inherently harder because the syntax is more uniform but the semantics vary more
that's counter-intuitive
That makes sense. The syntax doesn’t express as much. It’s essentially an AST.
invocation itself is an abstraction and thus inside calls lurk lazy/eager eval (function/macro), unstated structure (literal maps), flow control, etc
https://tonsky.me/blog/clojurefmt/ there is an alternative opinion on the formatting rules
in nutshell — there are just two rules: • Multi-line lists that start with a symbol are always indented with two spaces, • Other multi-line lists, vectors, maps and sets are aligned with the first element
git diff
has the -b
flag though, so diffs can look essentially the same, whether you align maps or not.
https://git-scm.com/docs/git-diff#Documentation/git-diff.txt--b
I use these. They stay out of my way. That makes me happy.
Recently there was a question of suitability of Clojure for certain types of computation. One of the downsides that was mentioned was higher memory pressure. But two performance upsides of FP are easier parallelisation and caching/memoization, since we’re dealing with (pure) functions in much larger quantities. How naive is it to think that it could be beneficial to skew to scaling vertically rather than horizontally given these tradeoffs? AKA requesting/using more cores and more memory, while optimising code to be concurrent, with heavy use of memoization (at the right places) instead of building smaller pieces that are scaled more horizontally with more machines (and more IO)?
Also if anyone has recommended reading about this issue I would be stoked!
martin thompson has talked a lot about vertical vs horizontal. specifically, the limitations imposed by amdahl's law and little's law. He's done a bunch of interesting writing and given presentations on the subject. here's two to get started: • https://www.infoq.com/presentations/mechanical-sympathy/ • https://www.infoq.com/presentations/LMAX/
another notable proponent of vertical scaling is the stack overflow team: http://highscalability.com/stack-overflow-architecture
thank you @smith.adriane!
saying clojure has "higher memory pressure" is tricky, because it is open ended, higher than what? a better way to put might be "clojure leans hard on the garbage collector"
although even that is problematic, because some things like everything being references and strings taking a lot of memory, are not features of clojure but of the jvm (and subject to change as the jvm changes, the string thing has gotten debatable better)
thx!
and the oracle and openjdk jvms ship with multiple different possible gcs, along with alternative jvms like zing shipping with their own high performance gc
so sort of maybe you can say something like "for a given task, among some set of programming languages, with naive task implementations, assuming the jvm languages would tend towards using more memory then others, and assuming clojure would tend to use more memory than java, would not be terrible starting assumption"
that's the long term dream of much fp lang development (it's what haskell banks on especially), it's still a strategy and still has trade offs though
(to be clear I wasn't saying "don't use clojure because it uses too much RAM", but when prompted for use cases where you wouldn't use clojure I listed some criteria, and if you meet multiple criteria clojure might be an unpragmatic choice)
in real world cases these trade offs increase complexity of code for high performance in a specific use case the drawback here (generally) is that your code is harder to write and read, and outside the specific target case it is worse than the naiive approach
Hey ! I'm working on a fullstack Clojure(Script) project. The backend is a pedestal API, and the frontend is a Reagent app that calls this API. I'm wondering if an "instrospection" tool exists to introspect the backend API and generate frontend services that I could just call with apropriate params. Ever heard of something like this before ?
If i have a list of hashmaps how can i get a new list with hashmap only with the specific keys included?
(def data [{:user "foo"
:name "foo-name"
:age 20}
{:user "bar"
:name "bar-name"
:age 24}])
[{:user foo, :name foo-name, :age 20} {:user bar, :name bar-name, :age 24}]
I want to only get the keys and values from a subset like :user
and :name
[{:user foo, :name foo-name} {:user bar, :name bar-name}]
@marco.pasopas (select-keys m [:user :name])
You should have a look at select-keys
https://clojuredocs.org/clojure.core/select-keys
Need to refrase my question 🙂 I want to get the keys / values from the list of hashmaps
@noisesmith Need to refrase my question 🙂 I want to get the keys / values from the list of hashmaps..
[{:user foo, :name foo-name, :age 20} {:user bar, :name bar-name, :age 24}]
to
[{:user foo, :name foo-name} {:user bar, :name bar-name}]
(map (fn [m] (select-keys m [:user :name])) data)
If you can do it once you can do it many times with map
Yes, then you can map through the list with (mapv #(select-keys % [:user :name]) data)
@dpsutton Thanks!! Going to digest how this works 🙂
yeah, I'd avoided the specific solution (because you might already be iterating the collection somewhere), but map is what usually get used
Thanks all for answering a real newbie question 🙂
for sure. check out (doc map)
(or use your editor specific commands to see documentation) for an explanation of how map works
Thank you for those pointers!
Maybe something like swagger is what you are after. Looks like there is support for ring - https://github.com/metosin/ring-swagger https://github.com/metosin/ring-swagger-ui I have only used it with Java personally, so I can't vouch for those libraries!
Thanks, I'll have a look rn 😉
Turns out it's super easy to get the example going, not sure on how easy it would be to add in later:
lein new compojure-api dice-api \
&& cd dice-api/ \
&& lein ring server
I've already used swagger on non-clojure projects.
The lib route-swagger
seems to support pedestal APIs' route definitions like here : https://github.com/frankiesardo/route-swagger/blob/8ebab45d03cb43fdec323b955f5ae4c152814d39/example/src/sample/service.clj#L279
Great. Thanks for the hint
Clojurists, i believe you'll know how to do this easily, and i'm having trouble
it's a simple transformation:
[:a 1 :b 2 :c 3]
-> {:a 1 :b 2 :c 3}
just realized i can use partition
to do this 😄
@matthewlisp hash-map
(apply hash-map [:a 1 :b 2]); => {:b 2, :a 1}
apply assoc
would also work if hash-map
didn't exist
Does anyone know how to deploy the static files created with Clojurescript to Heroku? I'm getting an error when I try to deploy the whole repo.
Does anyone know if their is a library that recreates this, or is similer. Its a checkbox but in the command prompt. This is an example when creating a new gatsby project. You hit enter and it puts a start by that line. I tried pretty.cli, but its really buggy for my computer.
I don't think lanterna has that built in, but it has the pieces you could use to do that https://github.com/mabe02/lanterna
currently, only support for fullscreen (via lanterna), https://github.com/phronmophobic/terminal-todo-mvc
Ill give it a shot. I have been wanting to learn how to use java from clojure anyways. 2 birds 1 stone right.
@santosx99xx, it's also graalvm compatible
Ill check this out too.
Thank you.
if you have any questions or run into any issues, feel free to ping me or file an issue
there are many options in the jvm itself to do that as well (and for the most part the only hard things about interop are that java apis tend to be worse than clojure ones and inheritance sucks)
Using google translate sometimes i get a result back such as "It's time"
Is there a way to turn that back into a normal apostrophe / etc?
url decode?
it's not a URL though, you need an HTML unescape, which seems not to be present in the vm
(which I found surprising)
gasp
the googles say use some random apache lib, but I can't tell you if that's even worth it
maybe it's enough to do a regex for apostrophes and that jazz
a regex that matches character escapes then uses the Char constructor shouldn't be hard
https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
a spec catalogue for christmas... how did you know??
xD
mm the results i'm getting are the #&38; variety
i can't be the first human on the internet with this problem
)user=> (Character/toString 38)
"&"
that plus a regex
yes, people use the apache library
the jvm undoubtedly has infrastructure for dealing with this in its xml processing stuff, but who wants to deal with that
Pretty much the only one that arose was the apostrophe so... 1 regex later it's resolved XD
something that is incredibly frustrating about languages like JS is keeping track of all the things in your head that you need to change or not change at specific points in time, because equality checks for references and not for values and some libraries force you to think about these things. The more I write in Clojure, the more I realise how mentally taxing this is! That said, when dealing with such APIs with Clojure/Script: are there pragmatic techniques/pointers to contain this issue?