Fork me on GitHub
Adam Helins06:08:55

TIL you can chain several #_ in order to ignore the several following forms

💯 9
Timur Latypoff07:08:10

Yeah really convenient sometimes.


especially useful for ignoring out kv in a map

{:foo "foo"
 #_#_:bar "bar"
 :baz "baz"}


and the obligatory

{#_#_#_#_#_#_:foo "foo"
 :bar "bar"
 :baz "baz"}

Per Weijnitz06:08:03

Not super intuitive:

user=> (pop '(0 1 2))
(1 2)
user=> (pop  [0 1 2])
[0 1]

David Vujic06:08:00

Because of lazy lookup for lists and “latest item” for vectors right?


not about laziness, about the location that conj uses, AKA (equivalently) the position that a peek or pop should use, sharing the same underlying constraint: using the efficient position in the data structure for insertion / removal

👍 3

(on a higher level of design thinking, I think this is more intuitive if you avoid collapsing the queue abstraction of pop/peek and the implementation detail of the collection used)

Adam Helins06:08:27

It might look a bit surprising, but it is consistent. Using pop , peek, and conj, vectors and lists behave like stacks. They do not store data in the same order, but they behave the same when using those 3 fns


right, and the thing to watch out for is any mix of "first" or "last" or "rest" or "next" in the same code that uses peek / pop / conj

👍 9

these are two different domains that just happen to share a data structure by coincidence


I once had a massive app bug caused by someone calling "rest" instead of "pop" on a clojure.lang.PersistentQueue, therefore turning a FIFO into a LIFO queue and breaking a distributed algorithm


I probably wasted a month on that!


there might have been a change on PersistentQueue that causes rest to return a value that can't be used as a stack to prevent this error


or else my memory is incomplete and there was some other more subtle behavior that made sure that queue which became a seq then became a list

Per Weijnitz06:08:42

I agree it's consistent, when you know that lists and vectors are implemented in different orders. It's very easy to make mistakes though.


Right, and that's why I offer (the hopefully helpful) suggestion of how to avoid that mistake. It's a tricky failure state of the lispy "small number of data structures and many functions" approach that clojure uses, compounded by its "many composed interfaces on one data structure" design. Both are great decisions with consequences I don't want to do without, but it's good to know the pitfalls to watch out for.


if that makes any sense

Per Weijnitz07:08:04

That rest/pop-bug on PersistentQueue sounds like a nightmare


Hi, is it possible to retrieve arity information of an anonymous function using reflection?


Are you using Clojure? If so, you can just use meta (see :arglists):

user=> (meta #'clojure.core/map)
{:added "1.0",
 :ns #object[clojure.lang.Namespace "0x27b1284f" "clojure.core"],
 :name map,
 :file "clojure/core.clj",
 :static true,
 :column 1,
 :line 2727,
 :arglists ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]),
 :doc "Returns a lazy sequence consisting of the result of applying f to\n  the set of first items of each coll, followed by applying f to the\n  set of second items in each coll, until any one of the colls is\n  exhausted.  Any remaining items in other colls are ignored. Function\n  f should accept number-of-colls arguments. Returns a transducer when\n  no collection is provided."}


Thank you! Unfortunately I'm working with anonymous functions at the moment, so there does not appear to be any available meta-data.

Ben Sless09:08:13

 (fn ([a b]) ([a b c]))
 (filter (comp #{'invoke} :name))
 (map (comp count :parameter-types))
 (into #{}))


Thanks, this works great!

Ben Sless10:08:37

Be advised its performance is probably trash so I hope you don't use it on your hot path

Sam Ritchie19:08:29

@U1SB9U10C I actually might be able to help here!

Sam Ritchie19:08:02

this should give you what you need on anonymous fns


Thanks for this, Sam!

Sam Ritchie19:08:55

if you use the cljs version in there, know that it won't work in advanced compilation mode

Sam Ritchie19:08:08

but pretty good up to that!

Pradeep Battul16:08:20

👋 I’m here! What’d I miss?


where's the best place to ask questions about the websockets library sente?


wow, so many sente questions coming up


lol maybe we need a channel!

Sam Ritchie19:08:44

Woah, most epic pun of all time

😂 3

was completely unintentional, didn't even realize my own genius

Sam Ritchie19:08:17

asynchronous genius

Sam Ritchie19:08:24

sometimes it takes a bit 😉


maybe this is an x-y problem. i'm wondering about best practices for registering new :event-id handlers. is it better to register event handlers next to the business logic, or to register all event handlers in a distinct namespace, importing the business logic?


I wouldn't describe this as sente specific, I was reminded how sente worked from other recent questions

👍 3

yeah, that's why I said x-y problem. very often i don't know the best question to ask!


people in tech underestimate the power of being an intuitive / empathic conversationalist IMHO, the failure states are usually easy to recognize, and the benefits are big


and many of those failure states are softened / circuit broken by humility


put that into an AI and you don't need me around any more


hahaha maybe some day


(since I so often fail to do all those things well)


I'd do it in the same basic pattern you'd use with ring handlers and namespaces


perhaps with a multimethod instead of a router (a more general and less complex abstraction)


of course if you also don't know how you'd want to organize ring handlers, that's a further conversation topic :D


ha i don't know much about that either, so any resources you have would be good! I inherited/took over development of this app, so there's been a lot of learning as i go


right now, our routes are set up as (-> routes auth/wrap-user wrap-keyword-params ...etc), where routes is a compojure defroutes object


so with a multi-method approach, i'd define the defmulti in the core namespace, and then in the implementing namespaces, defmethod?


that's how I'd do it yes


you can wrap the defmulti in a middleware stack the same way you would a router, but it's simpler than a router


you could also put interceptors on it the same way you would in pedestal, these are very reusable techniques IMHO


I’ll second the recommendation to do one of those things. As your event handlers start proliferating, you’ll start noticing that you want to extract common patterns (like permission checks etc.), and middleware/interceptors are really useful there.


hm! i gotta read up on those. thanks for the help


how can i add a typehint for just clj in a cljc file? i was hoping (defn #?(:clj ^java.util.Date) foo [] ...)


does expanding to foo and repeating it help?


do i need to just use {:tag java.util.Date}


ah. i'll check


it's slightly repetitive but should do the right thing


it is blowing up with unmatched delimiter ) so its hard to diagnose


haha. putting the name in their twice works 😞


there's also ^{:tag #?(:clj ... :cljs ...)}


(defn #?(:clj ^java.util.Date foo :cljs foo) [] ...)


but I think name twice is better


thanks so much @noisesmith

🍻 3