test-check 2021-03-04

@murtazasakbari has joined the channel

it seems unlikely, but I think you should be able to get by with a single fmap

Equal length strings?

generate a string of more than n characters, generate a vector of n characters and indices, then fmap over both of those producing a pair of the string, and the string with characters swapped at the indices

(the indices will require some fiddling to work out right, but doable)

You could also generate edit operations

yeah, characters + indices are an edit operation

What I've done so far is generate a string, and then edit out parts of it at random start and end positions using subs, joins and replace

no, I don't think you can do it without an fmap

Random meaning calling rand-int or similar?

in order for the generator to work at all, you need to at the base to be able to turn 1 string in to a pair of strings

that is gonna be an fmap

I think generating edits is pretty easy, though it might be harder to aim for exactly N differences if you need that

Generating edits would shrink nicely I think

If you want to shrink toward fewer differences

;; written but not run
;; assuming strings of length 5 and differences of 3 characters
(gen/fmap
 (fn [string edits]
   (loop [[[shift index] & es] edits
          s (vec string)
          editted #{}]
     (if e
       (let [i (mod index (count s))]
         (if (contains? editted i)
           (recur (cons [shift (inc index)] es) s editted)
           (recur es
                  (update-in s [i] (fn [c]
                                     (char (+ 32 (mod (+ offset (- (int c) 32)) 126)))))
                  (conj editted i))))
       (apply str s))))
 (gen/tuple (gen/resize 5 gen/string-ascii)
            (gen/tuple
             (gen/tuple s-pos-int s-pos-int)
             (gen/tuple s-pos-int s-pos-int)
             (gen/tuple s-pos-int s-pos-int))))

(that mod 126 should maybe be mod 126 - 32)

and the fn has to destructure the vector, etc

Can you recur from there?

inside a loop? of course

I meant from non-tail position

I am pretty sure those are all tails

I thought I had run into not being able to recur from the first branch of if but I may well be getting mixed up with recur within try

yes, you can't recur across a try, logically a try pushes an exception handler on to a stack, so recuring across a try grows the exception handling stack

Thanks, that makes sense