Wow, I didn’t know case
took an unquoted list like that ("RUNNING" "REGIST")
!
Really cool
@seancorfield Just to double check, > Before returning, normally or abnormally, any finally exprs will be evaluated for their side effects. Means that even when exceptions occur, the finally clause will do cleanup?
Yes.
So if you have
(try
(do-something)
(catch Throwable t
(record-failure))
(finally
(i-always-run)))
then if do-something
succeeds, i-always-run
will be called, else if do-something
throws an exception, then record-failure
and i-always-run
will be called (in that order).I've been trying to figure out a nicer way to either use defprotocol
/`defrecord` better or something altogether different, but nothing really comes to mind. I wrote a simple library that has 2 protocols and 2 records. Both records "implement" both protocols, and one of the records is tree-like such that it has leaves which are "instances" of the other record and nodes which are instances of its own type. Additionally, one of the protocol's implementations in common to both records. I'm afraid to say it but seems like a decent fit for OO pattern? Would love to think of better way to do this! Source: https://github.com/ogeagla/clj-cayley-dickson/blob/master/src/og/clj_cayley_dickson/core.clj
Thanks in advance, this is a "just for fun" project I wrote and am using.
@ogeagla here are some thoughts:
- it’s not common to have an init function as part of an interface. it’s more common to have that as part of the helper functions you have like complex
- you might not need get-idx
and set-idx
, you could provide an implementation of the Associative
interface that does the right thing based on if it’s receiving an index or keyword. Not sure this is cleaner though. Implementing Indexed
probably also makes sense.
- there’s a lot of translating between the keyword names :a,:b and the indexes 0, and 1. It might be cleaner just to use indexes everywhere. I’m not sure there’s much benefit to being able to access Complex’s pieces via (:a my-complex)
or (:b my-complex)
. if you want to have better names for accessing the pieces of a Complex2, then imo, real
and imaginary
would be better names than a
and b
.
- I think some case
statements could help make some of the code more readable
eg. rather than
(if (< idx
(/ (:order this)
2))
(get-idx (:a this) new-idx)
(get-idx (:b this) new-idx))
do
(case idx
0 (get-idx (:a this) new-idx)
1 (get-idx (:b this) new-idx))
- I would probably add order
to the Nion
interface and implement it for both the Complex
and Construction
types. otherwise, order
should be listed as a field of Construction
for clarity
- the print warnings should probably be assertions or exceptions
- Since all the implementations for NionOps
are the same and seem to work with anything that implements the Nion
protocol, then you probably don’t need the NionOps
protocol. You can just have the functions.@ogeagla another suggestion i notice you're doing a few things. 1: creating a job. 2: polling for state success, 3: do something with the data. When I encounter this pattern, I'll often want to separate the polling for state change into a separate function so that my code is organized like:
(let [job (create-job ..)
fetch-job-result (await-for-completion #(fetch-job job)]
(download-result fetch-job-result)
I would push all the logic of polling & error handling into the function await-for-completion
fetchthanks for the great feedback @smith.adriane and @rymndhng
no problem 🙂 i use this pattern several times in my own code
I wrote my first clojure program, i am hoping to have someone with experience tear it up with brutal honesty about what is bad, what is weird, and suggestions to do things differently. If anyone is interested in helping I can send you some LTC for the trouble. PM me if interested, i'll be back on later tonight.
@matthewdaniel I meant post a link to the project here so folks here can review it... Seems inefficient to expect a bunch of folks to PM you and you have to send them all details...?