Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround to avoid to replace '\{' and '\}' to '\(compliment-hashmap' and '\)' respectively #87

Merged
merged 1 commit into from
Jul 11, 2022

Conversation

vmfhrmfoaj
Copy link
Contributor

In try-read-replacing-maps function, in order to read a context, replace '{' and '}' with '(compliment-hashmap' and ')' respectively without condition.
'\{' (literal '{') is also replaced with '\(compliment-hashmap'. (read-string cannot parse a string containing '\('.)

So if a context contains '{' or '}', can't extract variable names from the context due to safe-read-context-string return nil.
To avoid the problem, I fixed try-read-replacing-maps to replace '\{' and '\}' with '(char 123)' and '(char 125)' respectively before replacing '{' and '}'.

;; before changes:
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex
  \"Convert a glob pattern string to a regular expression.
  I additionally support '**' pattern. This pattern indicates all characters except the newline.

  Examples:
   (glob->regex \\\"/a/b/*\\\")       ;=> #\\\"/a/b/[^/]*\\\"
   (glob->regex \\\"/a/b/?\\\")       ;=> #\\\"/a/b/[^/]?\\\"
   (glob->regex \\\"/a/b/[abc]\\\")   ;=> #\\\"/a/b/[abc]\\\"
   (glob->regex \\\"/a/b/[a-c]\\\")   ;=> #\\\"/a/b/[a-c]\\\"
   (glob->regex \\\"/a/b/{a,b,c}\\\") ;=> #\\\"/a/b/(a|b|c)\\\"
   (glob->regex \\\"/a/b/\\\\*\\\")     ;=> #\\\"/a/b/*\\\"\"
  [input]
  (loop [[c & cs] input
         regex \"\"
         escaped? false
         in-bracket? false
         in-curly-bracket? false]
    __prefix__
    (= c \\{) nil
    (= c \\}) nil
    ))
"))
;; Evaluation count : 19890 in 6 samples of 3315 calls.
;;              Execution time mean : 29.990710 µs
;;     Execution time std-deviation : 86.132061 ns
;;    Execution time lower quantile : 29.840915 µs ( 2.5%)
;;    Execution time upper quantile : 30.066819 µs (97.5%)
;;                    Overhead used : 5.268679 ns
;;
;; Found 1 outliers in 6 samples (16.6667 %)
;; 	low-severe	 1 (16.6667 %)
;;  Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
nil

;; after changes:
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex ..."))
;; Evaluation count : 17676 in 6 samples of 2946 calls.
;;              Execution time mean : 34.312736 µs
;;     Execution time std-deviation : 189.613207 ns
;;    Execution time lower quantile : 33.954349 µs ( 2.5%)
;;    Execution time upper quantile : 34.449656 µs (97.5%)
;;                    Overhead used : 5.268679 ns
;;
;; Found 1 outliers in 6 samples (16.6667 %)
;; 	low-severe	 1 (16.6667 %)
;;  Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
nil

;; regular expression version:
#_(-> s
      (str/replace #"(?<=^|[^\\])\{" "(compliment-hashmap ")
      (str/replace #"(?<=^|[^\\])\}" ")")
      ...)
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex ..."))
;; Evaluation count : 6054 in 6 samples of 1009 calls.
;;              Execution time mean : 101.963995 µs
;;     Execution time std-deviation : 258.471182 ns
;;    Execution time lower quantile : 101.689522 µs ( 2.5%)
;;    Execution time upper quantile : 102.275322 µs (97.5%)
;;                    Overhead used : 5.268679 ns
nil

@@ -17,6 +17,8 @@
(try (binding [*read-eval* false]
(let [ns-aliases (ns-aliases *ns*)]
(-> s
(str/replace "\\{" "(char 123)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest adding some comments here explaining the need for this.

CHANGELOG.md Outdated
@@ -2,6 +2,8 @@

### master (unreleased)

- Fix completion of local bindings when a context contains '{' or '}' characters.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to mention here the relevant PR as well.

…' and '\)' respectively

In `try-read-replacing-maps` function, in order to read a context, replace '{' and '}' with '(compliment-hashmap' and ')' respectively without condition.
'\{' (literal '{') is also replaced with '\(compliment-hashmap'.

So if a context contains '{' or '}', can't extract variable names from the context due to `safe-read-context-string` return `nil`.
To avoid the problem, I fixed `try-read-replacing-maps` to replace '\{' and '\}' with '(char 123)' and '(char 125)' respectively before replacing '{' and '}'.

```clojure
;; before changes:
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex
  \"Convert a glob pattern string to a regular expression.
  I additionally support '**' pattern. This pattern indicates all characters except the newline.

  Examples:
   (glob->regex \\\"/a/b/*\\\")       ;=> #\\\"/a/b/[^/]*\\\"
   (glob->regex \\\"/a/b/?\\\")       ;=> #\\\"/a/b/[^/]?\\\"
   (glob->regex \\\"/a/b/[abc]\\\")   ;=> #\\\"/a/b/[abc]\\\"
   (glob->regex \\\"/a/b/[a-c]\\\")   ;=> #\\\"/a/b/[a-c]\\\"
   (glob->regex \\\"/a/b/{a,b,c}\\\") ;=> #\\\"/a/b/(a|b|c)\\\"
   (glob->regex \\\"/a/b/\\\\*\\\")     ;=> #\\\"/a/b/*\\\"\"
  [input]
  (loop [[c & cs] input
         regex \"\"
         escaped? false
         in-bracket? false
         in-curly-bracket? false]
    __prefix__
    (= c \\{) nil
    (= c \\}) nil
    ))
"))
;; Evaluation count : 19890 in 6 samples of 3315 calls.
;;              Execution time mean : 29.990710 µs
;;     Execution time std-deviation : 86.132061 ns
;;    Execution time lower quantile : 29.840915 µs ( 2.5%)
;;    Execution time upper quantile : 30.066819 µs (97.5%)
;;                    Overhead used : 5.268679 ns
;;
;; Found 1 outliers in 6 samples (16.6667 %)
;; 	low-severe	 1 (16.6667 %)
;;  Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
nil

;; after changes:
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex ..."))
;; Evaluation count : 17676 in 6 samples of 2946 calls.
;;              Execution time mean : 34.312736 µs
;;     Execution time std-deviation : 189.613207 ns
;;    Execution time lower quantile : 33.954349 µs ( 2.5%)
;;    Execution time upper quantile : 34.449656 µs (97.5%)
;;                    Overhead used : 5.268679 ns
;;
;; Found 1 outliers in 6 samples (16.6667 %)
;; 	low-severe	 1 (16.6667 %)
;;  Variance from outliers : 13.8889 % Variance is moderately inflated by outliers
nil

;; regular expression version:
      (str/replace #"(?<=^|[^\\])\{" "(compliment-hashmap ")
      (str/replace #"(?<=^|[^\\])\}" ")")
      ...)
(criterium.core/quick-bench (try-read-replacing-maps "(defn glob->regex ..."))
;; Evaluation count : 6054 in 6 samples of 1009 calls.
;;              Execution time mean : 101.963995 µs
;;     Execution time std-deviation : 258.471182 ns
;;    Execution time lower quantile : 101.689522 µs ( 2.5%)
;;    Execution time upper quantile : 102.275322 µs (97.5%)
;;                    Overhead used : 5.268679 ns
nil
```
@vmfhrmfoaj
Copy link
Contributor Author

@bbatsov Updated. Thank you for the review.

@bbatsov bbatsov merged commit c8b107d into alexander-yakushev:master Jul 11, 2022
@bbatsov
Copy link
Collaborator

bbatsov commented Jul 11, 2022

I've cut 0.3.14 that includes your fix and hopefully addresses #86 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants