Fork me on GitHub

Hey so another quick question: for error handling, e.g sending wrong request parameters or invalid operations, is it ok to return nil all the way up until the service can treat it and respond the request with 4xx? Meaning the request handlers will look something like:

(defn get-something
  (let [value (get-function params)]
    (if value
and then get-function will probably be something like
(defn get-function
  (let [value (try-to-get params)]
    (if value
and that will probably continue... or is there a better way to do so?


I think this is reasonable, unless you want to give more specific error for different failures.


That second function could be

(defn get-function
  (when-let [value (try-to-get params)]


If you want some very simple, basic error handling/reporting, you might look at @hp_pedrors


Hmm I was thinking of returning an error code message, along with the value, so I can use globals and determine which message to send as well.


Anomalies supports error code (category) + message.


You could return {:ok value} or {:cognitect.anomalies/category ... }


Interesting! I'll take a look into it.


It's just data. You just decide on your conventions, write a spec, and off you go.


Not really pattern-matching, but I’ll sometimes do:

(let [[a b] my-vec]
  (if (nil? b)
    (do-thing a)
    (do-other-thing a b)))


in what way?


cljs.user=> (case (count [1 2 3])
       #_=>   1 "one"
       #_=>   2 "two"
       #_=>   3 "three")


You can use apply to call you various arity functions


(case (count my-vec)
  1 (apply some-fn my-vec)
  2 (apply some-fn my-vec))


Well if some-fn is overloading args, you don't even need case it'll be smart enough to dispatch on the argument count (edit, meant case, you still need apply)


Destructuring is not pattern matching


I think Rich Hickey has an issue with pattern matching


Because it complects two things


So destructuring is for getting things out of a structure.


And after that, to perform conditional logic, you use conditional constructs


^ @hp_pedrors That would be good for you to watch, based on our thread about error results.

thanks2 4

You're coupled your flow to the structure


If you change your structure, you break all your conditional logic


Ya, but not your conditional logic


Getting something out of a structure has to be coupled to the structure.


That is, unless it is a search, but like getting a thing in a precise position will always be coupled


What do you mean by conditional logic that accesses?


What do you mean? The condition would come after after, like (if "no zip code!" x y)


Also, I'm not sure about get-in, since you're right, it does a simple for of conditional with the default argument


But destructuring would not


It would just return nil or the value


Well, okay, it supports default as well 😛


Well, the first thing is that its a feature that complects binding and flow control. And Clojure likes to decomplect. So it chose to separate these two concerns.


The second thing is that pattern matching as a flow control mechanism is normally closed for extension. So Clojure offers multi-methods instead to avoid that.


normally closed*


Like, you can only extend it by modifying the pattern matching code itself


You can't from outside the function, for example say, oh and by the way, if the data matches to X do this other thing.


I mean, it is a pedantic argument


Well, in practice, nothing is always bad


But as a language feature, you have to think, I'm setting a norm, and is that norm likely to lead people to do things that I don't think is ideal most of the time?


Pattern matching has many libraries for it in Clojure. But Rich Hickey chose to make it more cumbersome to reach for, by not putting it in the core


To be honest, I'm not too sure myself, and now it has been a while since I've used pattern matching. Can you remind me in Elixir how you'd solve your above problem ?


> it was in core at one point, looks like Not sure what you mean there @deleted-user?


That's a Contrib library. Not part of Clojure.


Okay, that's what I remembered


Ya, I can only attribute it to wanting to encourage multi-methods over the use of case/switch


And even to some extent, protocols, though that won't apply to all pattern matching use cases


And I guess Spec now also does some form of pattern matching.


Ya, I can't say for sure. I've never worked professionally in a language with pattern matching, only toyed with those. I can't say I ever "miss" it in Clojure, but it could be because I've never used it enough.


Have a good night


Pattern matching is really good for a closed set of options where the compiler can help figure out whether you've matched all cases. That's what you get in languages like Scala (and Haskell I think).


Given Elixir is dynamically typed, I don't see how it can get that support -- so I can see how it would become brittle without compiler support.


@deleted-user For when you wake up... I also wonder if performance was a concern of Rich. You'll come to realize Rich Hickey is quite performance sensitive, and pattern matching has runtime overhead. So that could have been a strong reason to leave it out. Also... it was a choice for Clojure to be a Lisp with powerful extensions mechanisms. It is always okay in my opinion to reach for what you think is best, so if you really want pattern matching, a lot of people use core.match and defun ( as well in production and what not. So don't be shy. But maybe as a beginner, just to get accustomed, it's better to start practicing ways around it, and later, you can decide if you want it back and use a library.


My understanding in Elixir, and really in Erlang, is that it is actually unification


The = in Erlang is not assignment, but the unification operator


Which to be honest, I never understood the difference between unification and pattern matching 😛

Alex Miller (Clojure team)03:06:37

Rich did investigate pattern matching early on. perf is one key concern (scaling with cases), and the other is the closed nature of the match set. polymorphic systems like multimethods and protocols are both open for external extension.

☝️ 4

Sweet, seems like I guessed right 😁


I also do think it complects binding and flow. For example:

(defun foo
  ([false true] 1)
  ([true false] 2)
  ([true true] 3)
  ([false false] 4))



(defn foo [[a b]]
  (case [a b]
    [false true] 1
    [true false] 2
    [true true] 3
    [false false] 4))


Much easier to refactor the destructuring fn in case the structure changes. Say it becomes a map?

(defn foo [{:keys [a b]}]
  (case [a b]
    [false true] 1
    [true false] 2
    [true true] 3
    [false false] 4))
(defun foo
  ({:a false :b true} 1)
  ({:a true :b false} 2)
  ({:a true :b true} 3)
  ({:a false :b false} 4))


As I see it, the whole point of destructuring (or one of its big use cases) is decoupling the fn body to the structure of the args. In this case, the body doesn't know how to get a and b from the arg, it's abstracted in the destructuring. But pattern marching reintroduces some of the body's logic back into it.


Does Intellij/Cursive provide auto complete for Java classes ? It doesn't work for me and I didn't find anything ? :face_with_rolling_eyes:


There's currently a bug in IntelliJ that's interfering with symbol resolution, maybe that's related? There's more discussion of the issue in the #cursive channel.


Thanks , I will ask there,


Are there any cases where tests would run properly from repl if i (run-tests


but break when i lein test? i get exception ctual: java.lang.IllegalArgumentException: Cannot open <nil> as a Reader.


differences in dependencies between dev and test


thanks! i noticed i am missing one


i use with-profile so i don’t have to repeat deps. like make a :shared profile and start the test with lein with-profile +shared test

Suni Masuno14:06:22

Style question, does the & go on the same line or last line in arguments?

  & b]


  [a &


I put all arguments on the same line. There should be only a few of them anyway.


(Exception: when you’re destructuring a map with a lot of keys.)


In long-lived code, I always destructure in a let inside the defn. I have trouble visually parsing fn args that destructure inline.

Drew Verlee16:06:27

in joy of clojure 2 were shown this code:

(def very-lazy (-> (iterate #(do (print \.) (inc %)) 1)
                    rest rest rest))
;=> ..#'user/very-lazy

(def less-lazy (-> (iterate #(do (print \.) (inc %)) 1)
                    next next next))
;=> ...#'user/less-lazy
However this isn't what i get in my repl:
Clojure 1.10.0
(def very-lazy (-> (iterate #(do (print \.) (inc %)) 1)
                    rest rest rest))
(def less-lazy (-> (iterate #(do (print \.) (inc %)) 1)
                    next next next))
has next changed?


iterate has changed, in 1.7.0, I think?

Drew Verlee16:06:34

i suppose i'm having a hard time demonstrating that rest is more lazy then next.

(next '(1))
=> nil
(rest '(1))
=> ()
Doesn't, to me, demonstrate laziness, there are just different return values. The claim is that rest doesn't force realization of remaining elements, but i can't build an example to demonstrate this.

Alex Miller (Clojure team)16:06:42

I think it will depend on the seq you're using

Alex Miller (Clojure team)16:06:06

if you're digging into this area, this (historical) page from around the time of the seq overhaul may be of interest


() vs. nil does actually demonstrate it, but you need have more context, basically nil in this case means there for sure no more elements which means rest has inspected the contents (which is not a lazy operation). next returning () means there may or may not be more elements and next has not inspected the contents

Drew Verlee16:06:42

Thanks Alex! I'll take a look.

Drew Verlee16:06:03

"rest has inspected the elements" did you mean next here?


sorry, yes, swap them around


I never bothered remembering which is which, I use rest everywhere and call seq any place I want to nil pun


(rest predates next and used to behave more like next)


back in the day there was no "empty seq", just nil, and () was an empty list

Drew Verlee17:06:06

ah, ok. this example makes sense to me: In order to demonstrate the difference you need to make sure some other factor isn't going to eval the body and trigger the side effect (that helps show the lazyness). Here def does that, sense rest-test points at the un examined body as where next-test prints when called with def because it evals the body.

Drew Verlee17:06:53

i suppose its simpler to use rest everywhere except when your specifically going to use the nil return value to check an exit condition? Joy of Clojure seems to suggest the opposite though 🙂 > In general, we recommend that you use next unless you’re specifically trying to write code to be as lazy as possible.

Alex Miller (Clojure team)17:06:52

I tend not to use either of them most of the time

Alex Miller (Clojure team)17:06:55

instead, think in manipulating colls and seqs most of the time

Alex Miller (Clojure team)17:06:04

in case of loop/recur, lean on destructuring

Alex Miller (Clojure team)17:06:27

there can be some very subtle implications if working with walking nth items down via next/rest but you really can ignore that 99.9% of the time

Drew Verlee17:06:08

far enough. I think i understand them enough now to be aware of when the difference will matter. As you said, i mostly try to work with collections. Thanks again alex!


@alexmiller @didibus I guess I don't see why pattern matching is even being compared to multimethods and protocols, and why they're mutually exclusive. if I wanted to allow external extension I'd do multimethods and protocols (which elixir has as well), but most times I just want to do different things based on the structure I have (as in my original question) and the structures are used only within a function or namespace


Are you sure Elixir has multi-methods? I thought it only had Protocols?


Anyways, when you need a quick off the hand conditional restricted to a single function, normal conditional constructs are just fine. The danger is if you're using that same conditional logic over and over in different places, and if you are constantly having to extend it with new cases. That's when multi-methods will shine and be a better tool in my opinion


In your case. It seems what you're interested in is some kind of duck typing conditional. Like, what kind of structure do I have here. And based on that you would branch out.


Multi-methods are great for that. But they assume this will be used a lot. Like if your structures were top level entities of your app. It's overkill for you I agree


With your example, I think it's hard to understand. But in simple cases like yours, there are alternatives like you've seen. The fn overload is one, if you just want to branch on number of elements, it will also perform a lot faster.


I guess to see the difference, we'd need to have an example of pattern matching and multi-methods applied more to solve an architectural design issue.


I do think pattern marching can make some things simpler and clean and easy to read. I think the reason not to include it in the core was the fear that it would also quickly be used for larger things which multi-methods or protocols are better suited for.


So, another alternative, which I use, when your conditional logic itself is determined by the structure of data, is to use Spec


You can spec the various options using the or spec. And then use conform to know which one it conforms too in order.


The name of the first spec to match will be returned.


It is still more verbose then pattern matching though


Like this:

   :char (s/tuple any?)
   :char-count (s/tuple any? any?))
  [1 "c"]) 


That will return :char-count


If you pass it ["c"] it will return :char


Now you can imagine having a multi-method whose dispatch function is the above conform code.


Maybe you call it: decode


Still overkill in your case. But for a more complicated case it could be quite nice


I mean in your case, I think function overloading was pretty nice


After that, a conditional on count is probably second best, like with if or case if you have more then 2 branches


Ya. So I'm not gonna lie. Pattern matching in your situation also seem quite nice. I think for a lot of small simple algorithms, especially with recursive conditional branches, pattern matching is really good. And that's probably its sweet spot


And if you're doing a lot of these (and aren't trying to learn Clojure but know it well already 😉), it could make total sense to reach for core.match and defun in that scenario


Well, unless you cared about performance

Alex Miller (Clojure team)18:06:41

I feel like I don't commonly encounter this situation

Alex Miller (Clojure team)18:06:08

instead of applying, you could just destructure

Alex Miller (Clojure team)18:06:38

yeah, usually the more optional part is on the right so it's not weird


@deleted-user is there anything stopping you from having the function return char+cnt instead of cnt+char?


I think that would solve this problem from a syntax POV


yeah. I think what you’re doing now seems best 😄


you’ve uncovered a small shortcoming in Clojure’s default ability to express case matching. it doesn’t have as good of support for positional matching as, like you said as an example, Elixir


that’s good knowledge!


if you’re doing something that involves a lot of positional matching (like writing a parser/lexer) then you now know that you’re going to need some extra batteries if you decided to do it in Clojure


yes 😄 hopefully you also get to use some of Clojure’s stronger features like it’s rich polymorphic dispatch via multimethods and protocols


they work a lot better when combined with more descriptive data like maps and types/records


yeah. I find in applications, I tend to reach for multimethods. When writing a library, I tend to reach for protocols


Hey, can you suggest a Clojure repo that can be considered as "idiomatic"/well written? I know 101 level clojure and I want to study a repo to see if I'm actually going to like the language

☝️ 4
Alex Miller (Clojure team)19:06:49

many people recommend weavejester's as great example code


Is there any type of problem/task to solve that helps appreciating clojures stronger sides compared to other generic langs?(idk if this is good question tho)

Drew Verlee19:06:06

Clojure runs on the JVM, so it has the same pros and cons as the JVM. As a language, it has the same abilities as any other mainstream language. I would say the two of the stronger selling points are 1. code is data : which gives you the ability to pass functions as arguments and return them. 2. immutability as default: which means that hard to reason about state transitions become the exception and not the norm. I migrated from python -> ruby -> clojure and it's clear to me that everything i found useful in those languages has its roots in LISP and everything else ...


"code is data" is something else. First class functions/higher order functions is what gives you the ability to pass functions as arguments and return them.


"code is data" is what is behind macros: the ability to operate on Clojure code as a data structure -- transforming code prior to evaluation.


Yep, I've heard those a lot but havent had much mind-blowing moments tho.


Lots of languages provide 1st class fns and higher-order fns these days -- you can even get most of that in Java now 🙂


Code is data implies macros and ability to manipulute directly eval tree I guess


And macros are not anywhere near as "popular" in production Clojure code as many people would seem to think, when they first start learning about macros 🙂


For example, from our code base at work

Clojure source 279 files 66902 total loc,
    3118 fns, 641 of which are private,
    422 vars, 29 macros, 60 atoms,
    580 specs, 21 function specs.


(that's not including 20k lines of test code, but we don't track macros in that)


Given that Clojure is, by design, a "general purpose language", I think it's hard to point to a specific type of problem/task that shows Clojure's strengths.


It's great at data manipulation/transformation. It's great at concurrency (in various forms). Perhaps the real "killer aspect" of Clojure is a good REPL-driven development workflow? It's incredibly productive because of that extremely tight feedback loop.


Maybe its strong side is, since LISPs can look messy easily it forces me to write more fns, break-down the problem. Which is usually a good thing


REPL development (both using a actual repl or with immediate feedback using fighweel) is a big part of the "fun" here. It is hard to describe using toy examples since toy examples are usually read (not written) by those "outside" the clojure community.


I'd say Clojure excels at big boring enterprise apps


Just like Java does 😋


Except Clojure makes working on those fun again


So ETL processes, data pipelines, micro-services, SOA, etc.


Clojure is best when your state is inside a data store like S3, Mongo, MySQL, a file on disk. etc.


And your logic is mostly getting data, transforming it, putting it back, dispatching events to some other services, rinse and repeat


That makes it a really good choice as a backend for SPA apps as well


Which is where ClojureScript comes in handy, cause it excels at front end SPA


Clojure isn't so great for short lived programs, like grep, or other one shot quick command line tools


Or for high performance low level code, like graphics engine, audio processing, AAA games, etc.


Which is kind of unfortunate, because Clojure is better for big applications, but for small weekend projects, which is what people often play with first, it doesn't really shine. Though its definitely still good. But you won't really understand the benefits in those scenarios


Which all puts me in mind of my Clojure/West talk from many years ago "Doing Boring Things with an Exciting Language" 🙂


Haha, definitely, when the problem is boring, make your tools more exciting


It's also why I feel it's good to complement Clojure with one or two more languages, if you want to cover all possible use cases.


A lot of people complement it with Rust for low level high performance things.


I think to some extent OCaml can be used for this as well, or Go.


But these will also hit a limit. So I feel Rust really covers the other half of Clojure. Or Nim, C, C++ as well.


For scripts that don't need high performance, you have ClojureScript or Joker which work very well, and are easy to pick up as they are mostly Clojure. You can even use Clojure most of the time. Like, if you don't need uttermost performance, you can generally also accept the slower start time of Clojure


Almost everything I do is server-side, long-running processes, so "all Clojure" is fine 🙂


The last bit I think is not covered is Android and iOS development. ClojureScript works for that though


But I try to follow Pragmatic Programmer advice of learning a new language every year or so... Last year was Kotlin (quite nice). Go was several years ago (disappointed). Rust was in between (liked it, but I don't do any low-level stuff these days).


Haha, ya me 2


Elm was another fun language to learn (several years ago).


But I like the thought that I've got all cases covered.


My next ones that I'm interested in strongly are Rust, Rebol, OCaml


Have you ever heard of Fantom ?


Rust is fascinating. I haven't looked at Rebol. I did look at OCaml years ago (but ended up learning F# instead!).


I actually really like that language. But it is so unpopular


Rebol looks really interesting from a meta programming level


I think it might win as the next language I want to try


Heard of Fantom. Never looked at it.


It's basically taking DSLs to the extreme


Oh Fantom. Ya


Its like what I'd want Java to be


It's like how I find C# to be a better attempt at Java, and then I find Fantom to be a better attempt at C# :p


Though... like Go, it only has generics for bundled data structures


Have you tried Kotlin? That does a good job of being a "better Java".


I never tried it no. But I've had to browse Kotlin source to debug things before


But my first impressions weren't that great to be honest


I feel a little similar to how I feel about Scala. It tries and carve that weird middle of almost FP, but not really, almost hindley Milner, but not really


And I'm not sure I like it


I did Scala for about 18 months for work. I liked it at first and gradually grew to like it less and less, the more I worked with it. 🙂


Hello. I'm wondering if someone can point me in the right direction to correct this log format issue. I'm using timbre for logging on Windows, and when I log an exception with timbre, I see all these characters that I think are ascii encoding or something? Is there something I can use to make the printing look as it should?


My first line of attack would be to see if you can get a terminal on windows that supports ansi colour codes, but that's outside my knowledge - if you can't do that, you can turn off timbre colour codes for stacktraces. see


what are you running your repl in?


Ah thanks. Tried powershell and cmd


do you have git bash laying around?


you can turn off aviso.pretty, that's what colorizes


Ah I see. I may take that route. I do have git bash. I can try that too


Update: I found on stackoverflow that: >in latest Windows 10, you can enable ANSI in conhost via the following reghack -- in HKCU\Console create a DWORD named VirtualTerminalLevel and set it to 0x1; then restart cmd.exe.


This worked for me 🎉


@brandon.ringe Alternatively, maybe check the TERM value (or any cmd equivalent) to see why it thinks your term supported ANSI when it apparently didn’t. Otherwise your logs might get littered with ANSI escapes too.

👍 4