0
votes

I have written several functions that input strings and use varying regular expressions to search for patterns within the strings. All of the functions work on the same input [string]. What is the optimal way to combine all such functions into a single function?

I had tried combining the all of the regular expressions into a single regex, but ran into issues of degeneracy. Whereby the pattern fit multiple regular expressions and was outputting incorrect results. Next, I tried using the threading arrows -> and ->> but was unable to get those to work. I believe this might be the right option to use, but could not get the functions to run properly. So I am unable to test my hypothesis.

As an example of two functions to combine consider the following:

 (defn fooip [string]   
 (re-seq #"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b" string))

and

(defn foophone [string]
(re-seq #"[0-9]{3}-?[0-9]{3}-?[0-9]{4}" s))
3
What do you want to accomplish by combining them? Have a single function, which can match either a phone or IP? Or something else?ivant
The goal was to have a single function that could search for both patterns. Moreover, the general format to combine multiple functions within Clojure optimally.sunspots

3 Answers

7
votes

If you have multiple functions that you want to combine into a function that will return the result of applying each function to the same input, that is exactly the purpose of juxt.

(def foo (juxt foophone fooip))

(foo "555-555-5555 222.222.222.222 888-888-8888")
;=> [("555-555-5555" "888-888-8888") ("222.222.222.222")]
2
votes

Your question is a little vague, but the threading arrows' purpose is to apply multiple functions sequentially to the output of each other: (-> 1 inc inc inc), for example, is equivalent to (inc (inc (inc 1))).

From your code samples, it looks like you have multiple regexes you want to match against a single input string. The simple way to do that is to use for:

(for [r [#"foo" #"bar" #"baz"]] (re-seq r s))
1
votes

To check for both patterns you can use or:

(defn phone-or-ip [s]
  (or (matchphone s) (matchip s)))

There isn't one proper way to combine functions. It depends what you want to do.

P.S. There are ways to combine the regexps themselves. The naïve way is to just use | and parentheses to combine the two. I think there are optimizers, which can improve such patterns.