@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?
Tied together with bind and fmap?
Ha
Sure
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