Skip to content

Commit 56b7442

Browse files
committed
refactor: redefine String.replace
1 parent 14d76cc commit 56b7442

File tree

4 files changed

+112
-0
lines changed

4 files changed

+112
-0
lines changed

src/Init/Data/String.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ public import Init.Data.String.Substring
2222
public import Init.Data.String.TakeDrop
2323
public import Init.Data.String.Modify
2424
public import Init.Data.String.Termination
25+
public import Init.Data.String.ToSlice

src/Init/Data/String/Search.lean

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/-
2+
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Markus Himmel
5+
-/
6+
module
7+
8+
prelude
9+
public import Init.Data.String.Defs
10+
public import Init.Data.Iterators.Combinators.FilterMap
11+
public import Init.Data.String.Pattern
12+
public import Init.Data.String.ToSlice
13+
public import Init.Data.String.Slice
14+
15+
set_option doc.verso true
16+
17+
/-!
18+
# String API
19+
-/
20+
21+
public section
22+
23+
namespace String
24+
25+
section
26+
open String.Slice Pattern
27+
28+
variable {ρ : Type} {σ : Slice → Type}
29+
variable [∀ s, Std.Iterators.Iterator (σ s) Id (SearchStep s)]
30+
variable [∀ s, Std.Iterators.Finite (σ s) Id]
31+
variable [∀ s, Std.Iterators.IteratorLoop (σ s) Id Id]
32+
33+
34+
/--
35+
Constructs a new string obtained by replacing all occurrences of {name}`pattern` with
36+
{name}`replacement` in {name}`s`.
37+
38+
Examples:
39+
* {lean}`"red green blue".replace "e" "" = "rd grn blu"`
40+
* {lean}`"red green blue".replace "ee" "E" = "red grEn blue"`
41+
* {lean}`"red green blue".replace "e" "E" = "rEd grEEn bluE"`
42+
* {lean}`"abc".replace "" "k" = "rakbkck"`
43+
-/
44+
@[inline]
45+
def replace [ToForwardSearcher ρ σ] [ToSlice α] (s : String) (pattern : ρ)
46+
(replacement : α) : String :=
47+
s.toSlice.replace pattern replacement
48+
49+
end
50+
51+
end String

src/Init/Data/String/Slice.lean

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ prelude
99
public import Init.Data.String.Pattern
1010
public import Init.Data.Ord.Basic
1111
public import Init.Data.Iterators.Combinators.FilterMap
12+
public import Init.Data.String.ToSlice
1213

1314
set_option doc.verso true
1415

@@ -36,6 +37,12 @@ public section
3637

3738
namespace String.Slice
3839

40+
instance : HAppend String String.Slice String where
41+
-- This implementation performs an unnecessary copy which could be avoided by providing a custom
42+
-- C++ implementation for this instance. Note: if `String` had no custom runtime representation
43+
-- at all, then this would be very easy to get right from Lean using `ByteArray.copySlice`.
44+
hAppend s t := s ++ t.copy
45+
3946
open Pattern
4047

4148
/--
@@ -349,6 +356,22 @@ Examples:
349356
def dropPrefix [ForwardPattern ρ] (s : Slice) (pat : ρ) : Slice :=
350357
dropPrefix? s pat |>.getD s
351358

359+
/--
360+
Constructs a new string obtained by replacing all occurrences of {name}`pattern` with
361+
{name}`replacement` in {name}`s`.
362+
363+
Examples:
364+
* {lean}`"red green blue".toSlice.replace "e" "" = "rd grn blu"`
365+
* {lean}`"red green blue".toSlice.replace "ee" "E" = "red grEn blue"`
366+
* {lean}`"red green blue".toSlice.replace "e" "E" = "rEd grEEn bluE"`
367+
* {lean}`"abc".toSlice.replace "" "k" = "rakbkck"`
368+
-/
369+
def replace [ToForwardSearcher ρ σ] [ToSlice α] (s : Slice) (pattern : ρ) (replacement : α) :
370+
String :=
371+
(ToForwardSearcher.toSearcher s pattern).fold (init := "") (fun
372+
| sofar, .matched .. => sofar ++ ToSlice.toSlice replacement
373+
| sofar, .rejected start stop => sofar ++ s.replaceStartEnd! start stop)
374+
352375
/--
353376
Removes the specified number of characters (Unicode code points) from the start of the slice.
354377

src/Init/Data/String/ToSlice.lean

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/-
2+
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Markus Himmel
5+
-/
6+
module
7+
8+
prelude
9+
public import Init.Data.String.Defs
10+
11+
/-!
12+
# The `ToSlice` typeclass
13+
-/
14+
15+
public section
16+
17+
namespace String
18+
19+
/--
20+
Typeclass for types that have a conversion function to `String.Slice`. This typeclass is used to
21+
make some `String`/`String.Slice` functions polymorphic. As such, for now it is not intended that
22+
there instances of this beyond `ToSlice String` and `ToSlice String.Slice`.
23+
24+
To convert arbitrary data into a string representation, see `ToString` and `Repr`.
25+
-/
26+
class ToSlice (α : Type u) where
27+
toSlice : α → String.Slice
28+
29+
@[inline]
30+
instance : ToSlice String.Slice where
31+
toSlice := id
32+
33+
@[inline]
34+
instance : ToSlice String where
35+
toSlice := toSlice
36+
37+
end String

0 commit comments

Comments
 (0)