# How to properly create a single generator from two or more generators

**URL:** https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238
**Category:** Beginners
**Created:** [March 5, 2025, 4:18am UTC](https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238 "2025-03-05T04:18:01Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![metatron](https://clojureverse.org/user_avatar/clojureverse.org/metatron/32/5609_2.png) [@metatron](https://clojureverse.org/u/metatron)
#### Post date: [March 5, 2025, 4:18am UTC](https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238/1 "2025-03-05T04:18:01Z")

</div>

Hello I’m trying to use test.check to generate a string that is formatted as MM/dd/yyyy.

I have the following function

```auto
(defn- gen-date [start end]
  (tgen/let [months (tgen/choose 1 12)
             days (tgen/choose 1 31)
             years (tgen/choose start end)
             padding (fn [num-to-pad]
                       (if (< 1 num-to-pad 9)
                         (clojure.string/join "" [0 num-to-pad])
                         (str num-to-pad)))
             month-str (tgen/fmap #(padding %) months)
             day-str (tgen/fmap #(padding %) days)
             year-str (tgen/fmap str years)]

    (let [m (tgen/one-of [month-str])
          d (tgen/one-of [day-str])
          y (tgen/one-of [year-str])]
      (tgen/fmap clojure.string/join "/" [m d y]))))

```

I can’t seem to wrap my head around the last step which is to merge all the generators into a generator that will produce the final string.

tgen is an alias for test.check.generators. Any insight will be greatly appreciated.

---

<div class="post-metadata">

### Author: ![MartinPuda](https://clojureverse.org/user_avatar/clojureverse.org/martinpuda/32/4780_2.png) [@MartinPuda](https://clojureverse.org/u/MartinPuda)
#### Post date: [March 5, 2025, 5:49am UTC](https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238/2 "2025-03-05T05:49:59Z")

</div>

If your intent is to generate dates, note that any of these approaches can return non-existing dates- e.g. Feb 31.

This function will return one string:

```auto
(defn- gen-date [start end]
  (let [months (tgen/choose 1 12)
        days (tgen/choose 1 31)
        years (tgen/choose start end)
        padding (fn [num-to-pad]
                  (if (<= 1 num-to-pad 9)
                    (clojure.string/join "" [0 num-to-pad])
                    (str num-to-pad)))
        month-str (tgen/fmap padding months)
        day-str (tgen/fmap padding days)
        year-str (tgen/fmap str years)]
    (->> [month-str day-str year-str]
         (mapv tgen/generate)
         (clojure.string/join "/"))))

(gen-date 2005 2014)
=> "01/28/2006"
(gen-date 2005 2014)
=> "05/12/2005"
(gen-date 2005 2014)
=> "10/14/2013"

```

And this one returns generator:

```auto
(defn- gen-date2 [start end]
  (let [months (tgen/choose 1 12)
        days (tgen/choose 1 31)
        years (tgen/choose start end)
        padding (fn [num-to-pad]
                  (if (<= 1 num-to-pad 9)
                    (clojure.string/join "" [0 num-to-pad])
                    (str num-to-pad)))
        month-str (tgen/fmap padding months)
        day-str (tgen/fmap padding days)
        year-str (tgen/fmap str years)]
    (tgen/fmap (fn [[m d y]] (clojure.string/join "/" [m d y]))
               (tgen/tuple month-str day-str year-str))))

(tgen/sample (gen-date2 2010 2020) 10)
=>
("07/15/2020"
 "04/02/2016"
 "03/10/2011"
 "05/03/2011"
 "03/02/2019"
 "08/23/2015"
 "06/16/2015"
 "09/04/2017"
 "06/26/2019"
 "03/18/2019")

```

Shortened:

```auto
(defn- gen-date [start end]
    (->> [(tgen/choose 1 12) (tgen/choose 1 31) (tgen/choose start end)]
        (mapv tgen/generate)
        (apply format "%02d/%02d/%04d")))

(defn- gen-date2 [start end]
    (tgen/fmap (fn [[m d y]] (format "%02d/%02d/%04d" m d y))
               (tgen/tuple (tgen/choose 1 12)
                           (tgen/choose 1 31)
                           (tgen/choose start end))))

```

---

<div class="post-metadata">

### Author: ![metatron](https://clojureverse.org/user_avatar/clojureverse.org/metatron/32/5609_2.png) [@metatron](https://clojureverse.org/u/metatron)
#### Post date: [March 7, 2025, 1:48am UTC](https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238/3 "2025-03-07T01:48:26Z")

</div>

Thank you. I wish I had thought of format.

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [September 5, 2025, 1:48pm UTC](https://clojureverse.org/t/how-to-properly-create-a-single-generator-from-two-or-more-generators/11238/4 "2025-09-05T13:48:40Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
