Fork me on GitHub
#clojure
<
2020-08-19
>
Helins06:08:55

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

๐Ÿ’ฏ 3
Timur Latypoff07:08:10

Yeah really convenient sometimes.

bostonaholic14:08:38

especially useful for ignoring out kv in a map

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

bostonaholic14:08:37

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?

noisesmith06:08:09

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

๐Ÿ‘ 1
noisesmith06:08:24

(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)

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

noisesmith06:08:05

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

๐Ÿ‘ 3
noisesmith06:08:19

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

noisesmith06:08:09

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

noisesmith06:08:16

I probably wasted a month on that!

noisesmith06:08:56

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

noisesmith06:08:17

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.

noisesmith06:08:42

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.

noisesmith06:08:47

if that makes any sense

Per Weijnitz07:08:04

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

p08:08:26

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

p08:08:26

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

flowthing08:08:34

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."}

p09:08:43

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]))
 clojure.reflect/reflect
 :members
 (filter (comp #{'invoke} :name))
 (map (comp count :parameter-types))
 (into #{}))

p10:08:00

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

p19:08:52

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?

NoahTheDuke18:08:36

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

noisesmith18:08:58

wow, so many sente questions coming up

NoahTheDuke18:08:36

lol maybe we need a channel!

Sam Ritchie19:08:44

Woah, most epic pun of all time

๐Ÿ˜‚ 1
NoahTheDuke19:08:07

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 ๐Ÿ˜‰

NoahTheDuke18:08:24

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?

noisesmith18:08:14

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

๐Ÿ‘ 1
NoahTheDuke18:08:11

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

noisesmith18:08:26

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

noisesmith18:08:55

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

noisesmith18:08:13

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

NoahTheDuke18:08:24

hahaha maybe some day

noisesmith18:08:30

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

noisesmith18:08:30

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

noisesmith18:08:46

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

noisesmith18:08:21

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

NoahTheDuke18:08:02

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

NoahTheDuke18:08:05

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

NoahTheDuke18:08:29

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

noisesmith18:08:41

that's how I'd do it yes

noisesmith18:08:27

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

noisesmith18:08:54

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

flowthing18:08:22

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.

NoahTheDuke18:08:30

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

dpsutton20:08:11

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

noisesmith20:08:03

does expanding to foo and repeating it help?

dpsutton20:08:10

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

dpsutton20:08:13

ah. i'll check

noisesmith20:08:16

it's slightly repetitive but should do the right thing

dpsutton20:08:39

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

dpsutton20:08:09

haha. putting the name in their twice works ๐Ÿ˜ž

noisesmith20:08:23

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

dpsutton20:08:27

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

noisesmith20:08:30

but I think name twice is better

dpsutton20:08:41

thanks so much @noisesmith

๐Ÿป 1