This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # 100-days-of-code (13)
- # announcements (3)
- # beginners (122)
- # boot (17)
- # calva (19)
- # cider (27)
- # cljdoc (3)
- # cljs-dev (1)
- # clojure (138)
- # clojure-dev (5)
- # clojure-italy (5)
- # clojure-nl (20)
- # clojure-russia (3)
- # clojure-spec (14)
- # clojure-uk (119)
- # clojurescript (45)
- # core-async (2)
- # datomic (23)
- # editors (28)
- # emacs (35)
- # figwheel (2)
- # fulcro (26)
- # graphql (2)
- # hyperfiddle (11)
- # jobs (4)
- # luminus (5)
- # mount (2)
- # off-topic (52)
- # onyx (39)
- # reagent (86)
- # ring-swagger (2)
- # spacemacs (20)
- # tools-deps (9)
- # yada (4)
@cybersapiens97 The first element of the collection. The docstring explains how things work fairly explicitly.
([f coll] [f val coll]) f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the result of applying f to val and the first item in coll, then applying f to that result and the 2nd item, etc. If coll contains no items, returns val and f is not called.
With an initial val, those three cases become
(reduce f i [a b]) =>
(f (f i a) b),
(reduce f i ) =>
(reduce f i [a]) =>
(f i a)
Veterans of Clojure, in real world scenarios, how often you have to use Generative Recursion? Or it really depends on the kind of problem you’re tackling ?
Regarding Generative Recursion, I doubt most Clojurians even bother considering whether they're doing structural recursion or generative recursion -- it's going to depend on the shape of the problem.
A lot of the strictly recursive solutions from the Lisp world tend to be addressed by map/reduce as well. Or some other higher-order approach.
Wow, because it seems to me a totally different approach when dealing with non Structural Recursion. Thinking in terms of an algorithm, breaking the problem down into smaller easier solvable problems calls for some insight and having to warn or prevent the user for potential harmful inputs (non-termination)
Remember that most Clojurians are very pragmatic about just getting sh*t done. There are definitely some folks who think about academic nuances of algorithms but that's likely a minority here overall.
I wonder if this is bad for me, or if this is something I should stick with. Sometimes I feel I’m overthinking the problem or achieving the same results from people who just don’t pay attention to those things and do it faster...
As I recall, you pushed back when I suggested you really try think in terms of Clojure's abstractions -- as opposed to trying to think in terms of Lisp-like manipulation of concrete data structures...?
Hmm, I got it, I mean, I’ve spent a lot of time working on the HTDP book, (like a couple of months) and their recipe for designing programs just got stuck deeply in my mind, and their language didn’t really had a lot of abstractions, so I need time for a adapted mindset towards Clojure. For example, they enforce the specification of information as Data, for every function or problem you have to solve, and now I’m eager to work with Spec for doing that...
HTDP is good stuff. Gregor Kiczales online course based on it is good too. And I followed those practices for a while with Clojure as an experiment.
But there are definitely some gaps between the HTDP approach and what is idiomatic Clojure -- and a fluid Clojure workflow.
It was a great way of learning and understanding Functional Programming and also designing programs... it gave me a lot of insight about programming and computer science. And I think their approach (the complete recipe) still valid when I’m stucked, because it really helps to avoid looking at the screen and not really knowing the next step. I guess I’ll have to take the habit of program more and more in terms of CLJ abstractions, because their meant to make us productive right? Learning the behind the scenes is good for understanding the process but thinking about it while coding, seems unproductive, and I’m so hard stucked on their approach, that I have to think how the problem is solvable without using a high order function, so then I can translate/simplify the code using abstractions. That’s really slow, but in overall I’m enjoying my experience with Clojure for sure!
Yeah, that's one of the great things about HTDP: when you're stuck, it provides a good roadmap to figure out the little steps along the way.
I try hard to avoid thinking too much about the concrete behind the scenes stuff unless I'm not able to understand the behavior of something based purely on the abstractions. It's a shift worth making if you can.
Clojure is the most fun language I've ever used -- and I've used a lot over nearly four decades 🙂
Thanks for the great insights @seancorfield it’s nice and a relief to hear those things from a experienced person :)
FWIW, I sort of started with Lisp (1982/83) at university when my best friend decided to build a Lisp interpreter as his final year project.
(my final year project was to build an APL interpreter -- but I helped him test his project)
How nice, it seems to me that the Lisp approach to Programming is awesome for learning... wish they used it along the HTDP approach in the universities here at Brazil. They mostly use C, and you kinda learn to mimic your professor, that’s all
I learned about a dozen other languages on my own at university -- the computer lab was very tolerant of me borrowing every manual I could get my hands on 🙂
Btw, after all those years, do you think FP is a better approach towards the market problems against OOP? Or it really depends on the specific problem
After I graduated in '83, I did three years postgrad research into FP language design and implementation.
When Haskell came out, I was convinced it would storm the world (so of course I was very disappointed that the Haskell community seemed determined to avoid success at all costs!).
I learned OOP purely because that's what the market demanded but I did C/assembler mostly from 86 to 92, then C++ to 97, then Java.
Do you mean some particular kind of problems when you say "market problems against OOP"?
But I don’t get why OOP become so popular if FP was so much cleaner and easier to maintain
Computers are much much cheaper per Gbyte of RAM and GHz of processing power than they were 20-30 years ago. That makes a difference.
@andy.fingerhut not really, but I’m focused on web development, though I’ve never did code professionally, but I plan to use Clojure as back end for some projects of mine
Even in the 1980's a few software developers argued against C as being too expensive, vs. assembler.
OOP was sold as "modeling the real world" at a time when FP was still considered academic and requiring specialized and/or high-powered computers.
$2500 in 1980 bought an Apple II with 48Kbytes of RAM, 144 Kbyte floppy disks, no hard drive, 1 MHz CPU.
Do you guys have any books or resources, for someone who is going to start it’s own journey into web development, but as a company? Idk where to start when the subject is production methodology... and I don’t want to start as “just do it”
My first serious computer was a SAGE IV with 1Mb of RAM (a giant circuit board covered in 8Kb chips!) and a 20Mb HD.
@andy.fingerhut that’s insane, I almost cry when I see the big gap we made compared to the beginning of computers haha
I have probably heard of such a book, but not read one myself, so no personal knowledge to recommend for or against any books there.
I don’t have any professional experience, so I roughly know how software production works, I don’t know if I’m using the right therm (methodology). I want to know, how to approach the product production phase properly
There is a book "Ship it!" I've heard of, that is in that area -- reviews on Amazon, but first published 2005 and not sure whether it was written with enduring advice or short shelf life advice.
@cybersapiens97 You might like ‘the phoenix project’ it’s setup as a novel, and about moving towards devops in an organisation.
https://clojure.org/guides/weird_characters#__code_code_reader_eval has examples that fail:
Both fail (with either CLJ 1.9.0 and CLJ 1.10alpha8):
#="foo" ;... (def foo 1) #='foo
Syntax error reading source at (XX:0). Cause: Unsupported #= formAny tips, please?
is there a difference between
(-> states first) and
(first states)? no right? should the first ever be used?
I know I just wondered if there maybe still is some reason to use
(-> states first), in a macro or sth?
@bronsa Thank you. Is there anything similar that works (is it a typo, or misunderstood/misinterpreted functionality), or are those two examples completely wrong?
#= is mostly an internal implementation and the set of features it supports are not documented and very limited
in my experience it's relatively common to see
(-> x f) in production code; not totally sure if it's because people are in love with the arrow or maybe they were planning on adding more steps (or once had more steps that were factored out)
too many times I've done
(map fn coll) only to have to refactor it as
(->> coll (map fn)) because I need to do something else
emacs with paredit, or vim with paredit or vim-sexp both make it straightforward - I wouldn't be surprised to hear about other similar tools
Put the cursor here
(map fn |coll) and
convolute-sexp turns it into
(coll (map fn)) and you can just insert
->> (I believe it leaves the cursor in front of
coll? It's been a while since I used that in Emacs).
On macros: A general rule is to crate a function instead of a macro, if possible. Does
def have any different effect in (code generated by) a macro and in a function, please?
(def i 0) (defmacro i-inc  '(def i (inc i))) (defn i-inc-fn  (def i (inc i)))
Macros expand before code executes. Function bodies run only when called. But it's the same
def in both cases.
(and you should never see code that uses
def multiple times on the same var name)
the only time I ever use def inside some other form is for debugging, as it's more useful than just a println sometimes
For the above case, you'd either use an atom:
or you'd use
(def i (atom 0)) (defn i-inc-fn  (swap! i inc)) ;; and then use @i to get the current value
But, really, don't do this 🙂
(def i 0) (defn i-inc-fn  (alter-var-root #'i inc)) ;; and you can use plain ol' i to get the current value
Thank you. Yes, it's for a tool to help with debugging.
It will be debug/log indentation, hence thread-local. I guess I'll create it with
def :^dynamic, then
(binding [var new-value] ...) or
def ^:dynamic again.
you could do something like
(binding [*debug-print-indent* (inc *debug-print-indent*)] ....)
@noisesmith I tried to. If I want to keep the value at the top level, how do I define the variable? The following fails:
>> Can't dynamically bind non-dynamic var: user/i
(def i 0) (binding [i 2] i)
user=> (def ^:dynamic *foo-level* 0) #'user/*foo-level* user=> (defmacro more-foo [& body] `(binding [*foo-level* (inc *foo-level*)] [email protected])) #'user/more-foo user=> (more-foo (println "foo " *foo-level*) (more-foo (println "deeper" *foo-level*))) foo 1 deeper 2 nil
If I add a Clojure library as a dependency using a git coordinate in my
deps.edn, and that library uses
lein and its
project.clj, how are (if at all) its dependencies resolved?
I'm almost certain lein always generates a pom.xml which will be used to get the dependencies
But I'm not sure, I don't think it's really meant to be used like that. Any rebase/deletion of branch and it's gone, which is fine for testing. I sort of got the idea that created deps.edn with Ions in mind, and for that it's a great way to try some things out, without having to go to the usual release steps, and then pulling it Nexus/maven central
Just like you can't have dependencies on snapshots for maven releases, but I'm not sure it's impossible
tools.deps does not recognize
project.clj for dependencies in a Git (or local) repo -- so you can't do that.
As @U26FJ5FDM hints tho',
lein could generate
pom.xml which, if checked into Git, would allow you to depend on it (maybe). You'd be better off asking the library maintainer to add
deps.edn. Or you could fork the library and do either of those yourself @UBU6QCSJH...
Hello, recently i find myself having lots of
do block only because i need to log something. for example:
wondering if there's any good way to deal with logging cleanly? this kind of make a otherwise clean code messy..
(if true (log "something") (do (log "something else") (process-data)))
There's nothing wrong with that do block IMO. it doesn't look messy. If you must, you could either wrap your
process-data function in a
process-data-and-log function. What would be your ideal way of writing code with this kind of behaviour?
There are spy macros that will log the form, its value and then return the value. I find that very useful especially with a good editor. You just pop in the spy and then take it out when you are done. I’m on mobile so can’t look for one right now
@U0NLT4Z2Q I think your suggestion to have log inside of
process-data would make it looks nicer. thanks!