{ "str" string } { "quot" quotation }
{ "str'" string }
} ;
+
+HELP: exchange-subseq
+{ $values
+ { "len" { "a non-negative " { $link integer } } }
+ { "pos1" { "a non-negative " { $link integer } } }
+ { "pos2" { "a non-negative " { $link integer } } }
+ { "seq" { "a mutable " { $link sequence } } }
+}
+{ $description "Exchanges the contents of subsequences "
+{ $snippet "[pos1, pos1+len)" } " and " { $snippet "[pos2, pos2+len)" } " in "
+{ $snippet "seq" } ". Overlapping ranges are allowed. If either of the ranges exceeds the "
+{ $snippet "seq" } " length, throws an error before any modifications take place. If "
+{ $snippet "len" } " = 1, the behavior is equivalent to " { $link exchange } "." }
+{ $examples
+ "Non-overlapping ranges:"
+ { $example "USING: kernel sequences.extras prettyprint ;"
+ "2 0 3 \"01_34_\" [ exchange-subseq ] keep ."
+ "\"34_01_\""
+ }
+ "Overlapping ranges:"
+ { $example "USING: kernel sequences.extras prettyprint ;"
+ "3 0 2 \"abcdef\" [ exchange-subseq ] keep ."
+ "\"cdebaf\""
+ }
+}
+{ $side-effects "seq" }
+{ $see-also exchange } ;
{ { { 1 1 } { 2 2 } { f 3 } { f 4 } { f 5 } } } [
{ 1 2 } { 1 2 3 4 5 } zip-longest
] unit-test
+
+{ "34_01_" } [ 2 0 3 "01_34_" [ exchange-subseq ] keep ] unit-test
+{ "cdebaf" } [ 3 0 2 "abcdef" [ exchange-subseq ] keep ] unit-test
[ 2drop length ]
[ overd new-sequence-like dup ] 3bi
'[ [ [ _ nth-unsafe @ ] [ _ set-nth-unsafe ] bi ] each-integer _ ] call ; inline
+
+: exchange-subseq ( len pos1 pos2 seq -- )
+ [ 3dup max + 1 - ] dip bounds-check nip '[
+ 2dup _ exchange-unsafe
+ [ 1 - ] [ 1 + ] [ 1 + ] tri*
+ ] [ pick 0 > ] swap while 3drop ;