This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-12-30
Channels
- # announcements (2)
- # beginners (87)
- # boot-dev (9)
- # cider (3)
- # cljs-dev (72)
- # clojure (81)
- # clojure-europe (1)
- # clojure-france (1)
- # clojure-italy (1)
- # clojure-nl (2)
- # clojure-russia (212)
- # clojure-serbia (3)
- # clojure-spec (4)
- # clojure-uk (31)
- # clojurescript (82)
- # cursive (15)
- # datascript (2)
- # datomic (27)
- # dirac (11)
- # events (6)
- # fulcro (12)
- # hoplon (3)
- # jobs-discuss (1)
- # klipse (12)
- # off-topic (50)
- # overtone (8)
- # reagent (20)
- # reitit (7)
- # shadow-cljs (1)
Hi everyone, is there a way to turn off CIDER's stacktrace popping up everytime there is an error?
Hi everyone. Here with another basic question. If I have a vector and I would like to do something to its last element n times, how would I do that?
use for?
at the moment I do this:
`( dotimes [x 3] (take-last 1 p)) `
The last element three times: (repeat 3 (last v))
(if you know you have a vector you should use (pop v)
instead of last because it's O(1) and last is O(n))
ok so options are repeat, for and dotimes?
Yeah, (let [x (pop v)] (dotimes [_ n] ...))
where ... is the work you wanna do n times to x
Assuming it's purely side effectful.
And you don't care about the return value
@jaihindh.reddy how would it differ if i wanted the return val?
I didn't phrase it quite right.
If you want the return for each of the n times you do your work, you're better off doing (doall (map f (repeat n (pop v))))
.
Here all side effects execute right there and you get a sequence of the return values of f
for each of the n times.
Ok in that case ive done everything wrong
whoever said clojure was easy?
So this function is suppose to take a vector and add its elements by eachother
am i doing that wrong?
(that is my first step to making a pascal function )
What you seem to want is a function that takes a row of the pascal's triangle and returns the next row
But your function is putting zeroes on the ends whereas what you want are ones.
This function does just that:
(defn next-row [row]
(let [sums (mapv #(apply + %) (partition 2 1 row))]
(concat [1] sums [1])))
And you can create a pascal triangle of size n by doing (take n (iterate next-row [1]))
oh fuck i have no idea what your code does 😅
Sorry about that, lemme break it down a bit.
Lets say (def row [8 3 7 9 5])
(partition 2 1 row)
transforms it to a seq of consecutive pairs, i.e, ((8 3) (3 7) (7 9) (9 5))
And (mapv #(apply + %) (partition 2 1 row))
just takes that and adds the pairs up i.e, [11 10 16 14]
And finally we call that sums, and tack on a 1 on either ends
No its my bad for not quite knowing what I am doing
I'm a beginner too, and I'm sure there are more elegant ways of doing the same thing 😄
ok, so partition and mapv are the two fucntions I had not seen before
Check out all the arities of partition. Very handy
Maybe I jumped into doing thing too fast
PS: It got too long. Feel free to ignore 😅
Nah man. It just takes time. Keep at it. A couple of months ago I would have written the solution the same as you did. I noticed that people that come from imperative/OO paradigms initially use loop
, recur
, for
and let
a lot. Especially let
because that's what's familiar. Then slowly, you start to use map
, filter
and reduce
, and instead of creating locals everywhere, you start to compose transformations of data with ->
, ->>
and comp
. After that point, the more stuff understand in clojure.core
, the more expressive and elegant your code becomes. You don't find things like partition
, iterate
, reductions
, interleave
, interpose
and frequencies
in most languages' core libraries as generic sequence operations and so you're left to repeat the logic of these in terms of things like reduce
, and various utility libraries emerge. Clojure really gives you a rich vocabulary to express your logic, and gets out of your way in that sense.
Thanks, that does sound quite encouraging.
I only learn by doing and it looks like there are no tutorials that take you from 0 to intermediate. So I am doing my own excersices
@UECGQDP1C did you try
?
That's precisely what it does.
I couldnt figure out if they were in order
im reading through brave and true book
Do them in Elementary, Easy, Medium, Hard order. Ignore the suggestions it gives you after solving each problem. Also after you solve each problem, you can admire the elegance of others' weavings.
damn got stock on the 22nd
they are harder than I thought
What libraries is the community using to test ring-based apps? I found Kerodon (https://github.com/xeqi/kerodon), but looks like it is not being updated very often (maybe it does not need to)
what exactly are you looking to test? like, if the HTTP endpoint returns the correct thing?
The latter
For instance, filling forms, pressing buttons and checking results
there’s a clojure webdriver implementation here: https://github.com/igrishaev/etaoin
Thanks! I will take a look. Also, a more philosophical question about testing: doing this kind of html test feels like I am testing the same functionality twice. For instance, imagine a form to create a blog post. I can test two things: the html interaction through libraries like the ones we are talking about and the business logic for creating a blog post (validation, etc.)
Is it ok to have tests like this? I mean, checking for validation errors both on HTML and from the business logic function?
the problem is that end-to-end tests like selenium / etaoin are often a PITA to setup. or at the least, unfamiliar to most devs
+1 on the webdrivers being a PITA.
as your app grows and you start to “pour concrete” on portions of your app, then unit tests can help prevent breaking previous assumptions
If your front-end architecture looks something like fulcro's, UI is decomplected from all the other stuff in the front-end, and you can test your front-end app without webdrivers. ^ Just something I heard other people talk about and do. I'm clueless 🙂
My jaw dropped to the floor when I saw this: https://www.youtube.com/watch?v=qijWBPYkRAQ
haven’t watched the talk, but if you’re talking about something akin to shallow-rendering (testing the hiccup or react tree is correct), you still are not quite testing it end-to-end
Thanks guys
Evening
This may sound like a stupid question - especially for a functional language
I'm finding myself splitting a lot of logic that was otherwise just part of a function (eg. iterating a list and formatting a string) into separate functions
Is this something common?
I know that each function should ideally be a small unit of work for DRY and testability, but in the likes of Python, I'd never normally split parts out so granularly
I'm new-ish to Clojure but not to functional programming and I think the answer seems to be a qualified yes.
Seems like it's frequently done in the form of inline lambdas in addition to splitting out named functions, though.
I think the presence of map and other similar functions to work with collections kind of encourages it. I feel like I don't often see itertools map used in Python, but in Python I do use a lot of list comprehensions which are pretty Haskell-y/Clojure-y
@james662 can you give us an example where you feel there's unnecessary splitting going on?
If the smaller functions after the splitting still make sense in your domain, then it is good. On the other hand, if the newly split functions don't make sense anywhere except the original call-site, then that's not so good.
Well, I'm not sure if it's because I'm still new to the lisp syntax and I don't want to add too much to one place or what
I'm finding that where I may have had say 4 lines of logic to determine a variable, I'm resorting to a function
I;m not entirely against that because it kinda makes sense, but I'm not sure if this is idiomatic or overkill
I mean, I could nest those functions inside the format-bookmark
function with letfn
I guess
the fmt-name-or-alias
is pretty bad I realise, because returning ""
is dirty, but I was just wanting to get something working while I'm still learning
Nothing dirty about returning a empty string. I would personally write it like this:
(defn fmt-bookmark
"Formats a bookmark to a string"
[{:keys [name alias tags]}]
(let [fname (if alias
(format "%s /%s/" name alias)
name)
ftags (when (not (empty? tags))
(->> (map #(str "#" %) tags)
(clojure.string/join " ")
(format "|%s|")))]
(str fname " " ftags)))
A couple of possibly tangential points:
The name format-bookmark
suggests it returns a formatted bookmark. So the concerns of printing the result and caring about the index can be moved upstream.
As to whether fmt-name-or-alias should be factored out, it depends on whether it's useful elsewhere. I would move it out when needed.Sweet, makes sense. I keep looking for an excuse to use the threading macros because they seem so handy when I see them in example code
Also, I didn't realise I could have login in a let statement's expressions
which is obvious now
Also, because you aren't formatting the index here, you don't need format
here. And str
treats nil as an empty string, allowing us to use when
which removes the ""
from str-tags
unless I can get format
not to force nil
into "nil"
You could use str
to turn nil
into ""
. i.e. (format "%s" (str nil))
Your code looks fairly standard to me as far as splitting logic up into functions. One way to reduce the number of functions is to try and find generic logic and make one function that can handle multiple cases.
In your case:
(defn fmt
[name v fmt]
(if (nil? v)
(str name)
(format fmt name v)))
could eliminate two of the helper functionsanother way to change the way nil is handled is with fnil
.
(fnil format nil nil "")
, returns a function which acts the same as format
but when the third arg is nil
it will use ""
instead
That's good thinking, thanks for your help @trailcapital
I'm not all too worried about the efficiency etc. at the moment, I'm just trying to convert my thinking to the functional paradigm