Fork me on GitHub
#beginners
<
2022-07-10
>
popeye06:07:34

I was checking the logic of buddy-hasher https://github.com/funcool/buddy-hashers/blob/master/src/clj/buddy/hashers.clj#L174-L195 this has the line of code , but return something else (hash map) , How are we sure that it give us hash created by :argon2id?

(.init generator params)
    (.generateBytes generator ^bytes password hash)

rolt08:07:50

what do you mean ? hash is initialized as a byte array and then filled when calling generateBytes

popeye08:07:22

(.init generator params)
    (.generateBytes generator ^bytes password hash)

popeye08:07:40

how the function is helping in generating password?

rolt08:07:11

it's filling hash

popeye08:07:47

but hash is returned one above line right

hash       (byte-array 32)

rolt08:07:40

generateBytes mutates it

Muhammad Hamza Chippa06:07:39

Hi Guys, I am new to reframe and trying to render the array which is I am getting from the subscribtion @(rf/subscribe [:regions]). I can see the array is there in the array but I am unable to see it on the screen until I refresh it. @(rf/subscribe [:regions]) return a simple array like this ("Asia" "South America" "North America" "Africa" "Europe" "Oceania") . I am using a very simple code snippet from reframe tutorial.

(defn regions-filter []
  (let [regions @(rf/subscribe [:regions])]
    (fn []
      [:ul (for
            [region regions]
             ^{:key region}
             [:li region])])))

popeye07:07:44

I did not check the whole code, But concept is -whenever you make any changes, like an event is triggered then only you can see the values, here refresh is like event and value may getting updated in the db

popeye07:07:01

try updating a values in db using an event, you can see the values changing in UI

Muhammad Hamza Chippa07:07:18

I am not updating it, just defining the db at the time of runtime using reg-event-db and then reading it using rf/subscribe

popeye07:07:01

which link you are referring to

rolt08:07:51

where does the code come from ? i don't think you're supposed to deref the subscription in the outer function

Ben Wadsworth12:07:32

Someone with a bit more conceptual knowledge of re-frame might be able to chime in, by when reading https://day8.github.io/re-frame/subscriptions/ it points to view functions returning only hiccup and the usages of subscriptions happening within the view functions. What you have here is a function returning a “view function” which itself doesn’t have that subscription in scope. I don’t know the implementation or downstream affects of this, nor do I know what the calling code is like, but this does seem like you should just remove the function being returned and return the straight hiccup syntax

❤️ 1
sarna09:07:47

hey, does anyone use erlang/elixir-style error handling in clojure? to me it seems way more convenient than both exceptions (not very functional) and returning nil (information/context loss). if you're not familiar with it, they return maps like {:ok result} on success and {:error some-error} on failure, and then pattern-match on them on call-site. you could even chain them with some macro so the first error is returned (like err->> from https://adambard.com/blog/acceptable-error-handling-in-clojure/). would there be any disadvantages to this approach? also I'm not sure why Adam used a vector in their post instead of a map, I'd prefer having names for ok/err

Ben Sless12:07:00

The harshest reasoning you'll find against it is it reintroduces an either monad, and that monadic code does not really belong in Clojure. There's also the fact it's ad-hoc and basically broken by a typo. Why do that instead of just throw an error if something went wrong and catch it outside? You already have facilities around exception handling, and this does not introduce new syntax or abstractions

sarna13:07:05

ah - I somehow got the impression that exceptions were basically code smells in clojure and you should avoid them as much as possible. if that's not true, I'll just use plain exceptions as you suggested :)

Ben Sless13:07:55

It's useful to also differentiate between a general error, a specific error, and "nothing". If something just doesn't work and you don't care where or why, just return nil and use some-> to short circuit. If you have exceptional circumstances, throw an exception to break out of a sequence of computations. another option is composing CPS transforms or using interceptors, i.e. transform your functions to have an arity of [data on-success on-failure] where on-success is the next function and on-failure is whatever you'll call on error

Ben Sless13:07:27

interceptors drive this mechanism for you, you provide a sequence of maps with enter, leave, error keys (all optional)

Ben Sless13:07:47

if you use core.async you can use split

sarna14:07:30

that's very useful, thank you!

Ben Sless14:07:37

welcome 🙂 Do you have an example for your particular use case?

sarna14:07:42

nope. I started rewriting a program in clojure, was expecting to quickly run into exceptions and handling them. but I didn't have to handle any yet :)

Ben Sless15:07:26

Oh yeah, Clojure code isn't expected to throw often

Ben Sless15:07:49

Aren't exceptions just a special case of conditions and restarts?

sarna15:07:17

ty for the link - did any widely used libraries for conditions and restarts emerge in these six years between this vid and today?

sarna15:07:58

I don't want to start using something super niche straight away :) I'm still a clojure noob

Bob B17:07:42

As I understand it, yes, exceptions are basically a special case of conditions, which are kinda sorta like a continuation monad (but I'm not much of a CT expert, so that might be less than 100% accurate). I don't know if any of them are very widely-used (possibly in part because of the "plumbing" reasoning described by chouser at the end of the video), but there are a few condition system libraries on the clojure toolbox site. From my personal experience, I've never felt the need to take on one of the libraries, but I have used the dynamic binding version a couple of times for 'error condition handling' and once or twice for non-error situations.

👍 1
sarna18:07:17

I'll watch the full video later, hopefully it all makes more sense. thanks :)

Dustin Reed Morado19:07:49

Hi everyone, I am working through Chapter 15 of Getting Clojure and using the books source code which uses Leiningen the following works in CIDER:

(defn book-blurb [book]
  (str "The best selling book " (:title book) " by " (:author book)))

(s/fdef book-blurb :args (s/cat :book ::book))
;

;
(require '[clojure.spec.test.alpha :as stest])

(stest/check 'inventory.core/book-blurb) ; ({:spec
                                         ; #object[clojure.spec.alpha$fspec_impl$reify__1203
                                         ; 0x5315c84f
                                         ; "clojure.spec.alpha$fspec_impl$reify__1203@5315c84f"],
                                         ; :clojure.spec.test.check/ret {:result
                                         ; true, :num-tests 1000, :seed
                                         ; 1657480278677}, :sym
                                         ; inventory.core/book-blurb})
;
However, when I run the same bit of code using Clojure deps.edn I get a large stack trace with the error:
({:spec
  #object[clojure.spec.alpha$fspec_impl$reify__2518 0x1f14d17f "clojure.spec.alpha$fspec_impl$reify__2518@1f14d17f"],
  :clojure.spec.test.check/ret {:result #error {
 :cause "Could not locate clojure/test/check/generators__init.class, clojure/test/check/generators.clj or clojure/test/check/generators.cljc on classpath."
 :via
 [{:type java.io.FileNotFoundException
   :message "Could not locate clojure/test/check/generators__init.class, clojure/test/check/generators.clj or clojure/test/check/generators.cljc on classpath."
Any ideas on what is the difference between the two? At this stage of book I don’t really understand so much how the code works, but at least want to try and at least have all of the examples run. Thanks for any suggestions or help!

Alex Miller (Clojure team)19:07:49

the error is due to not including org.clojure/test.check lib in the deps

1
👍 1
Alex Miller (Clojure team)19:07:17

so probably that's a difference in project.clj to deps.edn

Dustin Reed Morado19:07:03

Thank you very much, yes I see now that test.check is in projects.clj and not in the main dependencies (but it is in the test alias using deps-new). Again appreciate the help!