Created
February 3, 2024 10:55
-
-
Save bsless/8b2572df1f9ffe9dfc8465ca417c9e2e to your computer and use it in GitHub Desktop.
Compare and contrast unclebob/functor ur example and different implementation tradeoffs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Baseline | |
(defn encrypt-if-direct-message [content tags] | |
(if (re-find #"^D \#\[\d+\]" content) | |
(let [reference-digits (re-find #"\d+" content) | |
reference-index (Integer/parseInt reference-digits) | |
p-tag (get tags reference-index)] | |
(if (nil? p-tag) | |
[content 1] | |
(let [recipient-key (hex-string->num (second p-tag)) | |
private-key (get-mem [:keys :private-key]) | |
sender-key (hex-string->num private-key) | |
shared-secret (SECP256K1/calculateKeyAgreement sender-key recipient-key) | |
encrypted-content (SECP256K1/encrypt shared-secret content)] | |
[encrypted-content 4]))) | |
[content 1])) | |
;; Functor | |
(def encrypt-if-direct-message | |
(functor | |
([content tags] | |
(if (is-direct?) | |
(encrypt-if-properly-referenced) | |
(leave-unencrypted))) | |
(is-direct? [] (re-find #"^D \#\[\d+\]" content)) | |
(get-p-tag-from-content | |
[] | |
(let [reference-digits (re-find #"\d+" content) | |
reference-index (Integer/parseInt reference-digits)] | |
(get tags reference-index))) | |
(encrypt-content | |
[] | |
(let [recipient-key (hex-string->num (second p-tag)) | |
private-key (get-mem [:keys :private-key]) | |
sender-key (hex-string->num private-key) | |
shared-secret (SECP256K1/calculateKeyAgreement sender-key recipient-key)] | |
(SECP256K1/encrypt shared-secret content))) | |
(encrypt-if-properly-referenced | |
[] | |
(<- p-tag (get-p-tag-from-content)) | |
(if (nil? p-tag) | |
[content 1] | |
[(encrypt-content) 4])) | |
(leave-unencrypted [] [content 1]))) | |
;; Factor to functions | |
(defn- direct? [content] | |
(re-find #"^D \#\[\d+\]" content)) | |
(defn- get-p-tag-from-content | |
[content tags] | |
(let [reference-digits (re-find #"\d+" content) | |
reference-index (Integer/parseInt reference-digits)] | |
(get tags reference-index))) | |
(defn- encrypt-content | |
[content p-tag] | |
(let [recipient-key (hex-string->num (second p-tag)) | |
private-key (get-mem [:keys :private-key]) | |
sender-key (hex-string->num private-key) | |
shared-secret (SECP256K1/calculateKeyAgreement sender-key recipient-key)] | |
(SECP256K1/encrypt shared-secret content))) | |
(defn- encrypt-if-properly-referenced [content tags] | |
(let [p-tag (get-p-tag-from-content content tags)] | |
(if (nil? p-tag) | |
[content 1] | |
[(encrypt-content content p-tag) 4]))) | |
(defn- leave-unencrypted [content] [content 1]) | |
(defn encrypt-if-direct-message | |
[content tags] | |
(if (direct? content) | |
(encrypt-if-properly-referenced content tags) | |
(leave-unencrypted content))) |
Another point brought up on Slack by @alexander-yakushev: less REPL friendly, which is somewhat associated with it being less test friendly. I can imagine wanting to tinker with the regex and having a lot of unnecessary concerns mixed in while I figure out the right regex and edge cases.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My inner pessimist just knows those functors won't remain small.
I also adopted a weird approach where I tend to avoid private functions. I prefer moving them to an
impl
namespace. This makes testing more convenient, and also shows some more trust in the user.On another subject, for performance, you could replace the lazily initialized vars backing refs with an array of size 1. That would allow you to pass primitive args, too.
If you want to avoid the allocated functions in
lets
, you can use them as templates and inline them. But inlining is both risky and hard