Details
-
Type:
Defect
-
Status:
Closed
-
Priority:
Minor
-
Resolution: Completed
-
Affects Version/s: Release 1.2, Release 1.3
-
Fix Version/s: Release 1.5
-
Component/s: None
-
Labels:None
-
Environment:HW/OS/SW indipendant - issue is part of java interface
-
Patch:Code and Test
-
Approval:Ok
Description
clojure.string/replace uses javas replace function to do it's work, the replace function has the tricky habit of 'double evaluating' the replacement string (third argument). This means that every \ in the string (so i.e. "
") is evaluated by the java code behind replace.
Since this behavior isn't documented it can lead to confusing errors, for example (made up semi real world example to explain the issue):
(clojure.string/replace "c:/windows/" #"/" "\\")
This should replace all unix folder separators with windows separators, this crashes with a index out of bound exemption since java tries to evaluate "
" as a semi regexp.
or
(println (str "\"" (clojure.string/replace "my string with \\ and \" in it" #"[\"\\]" (fn [x] (str "\\" x))) "\""))
The expected result would be:
"my string with \\ and \" in it"
the actual result is:
"my string with \ and " in it"
This should return an 'escaped' string, it does not since the 'double evaluation' of the return string results in \\\\ being reduced to
again.
Screened. This is an adequate fix for this particular problem, given the current API.
However, the long and complicated docstring proves that replace and replace-first should each be four separate functions:
code
replace-char [input char char]
replace-string [input string string]
replace-re [input pattern string]
replace-re-by [input pattern fn]
code
This is how these functions were originally written back in the days of clojure.contrib.str-utils. This would be a minor breaking change.