It all boils down to the fact that strings are immutable and are not
persistent.

What I was trying to say is that the operation of replacing one character
with another in an immutable and non persistent string is not a common one
and may be a sign of bad design. I was not commenting on the replacement of
a substring with another substring.

There is a function in clojure called assoc, which in case of immutable and
persistent vector returns new vector with element at a given index
replaced.

(assoc [:a :b :c] 1 :foo) => [:a :foo :c]

You may think that such function should be supported for the string (as
string is an immutable sequential collection of characters with a random
access to its elements), but the problem is that string is not a persistent
collection, which means that such replacement of a character must copy all
characters of an original string. (moreover, substring creates a copy too).

If, in you program, the string modification is an infrequent operation, use
substrings and str as you wish. If however the string modification is in
the performance critical part of the code, you should not be using strings.
Clojure offers persistent vector or even primitive persistent vector, which
supports assoc nicely.

There are times however when you do need a mutable collection. Clojure uses
a concept of transient collection here, which is a mutable collection with
a fast conversion operation to the immutable variant and with the check
that all operations upon the transient collection are executed within the
same thread.

While the Clojure has transient vectors, it does not offer a transient
string. The reasons are as follows:
- strings are not persistent and the concept of transients were designed
for persistent collections
- for performance and compatibility reasons, strings are java strings and
it is hard to extend existing java types with new clojure functionalities
- there is a StringBuilder class which offers all the functionality you
need.

So if you need a mutable string, you should use the StringBuilder class.

What would be a nice (in my opinion) addition to the Clojure is:
- transient string which wraps the StringBuilder, just for the convenience
- another substring-like function which does not copy its contents.

Finally, the Clojure convention is that it is not the choice of name which
sugests a mutability, but the bang (!) character at the end of the function
name, which denotes that the function produces side effects (e.g. mutates
some of its inputs).

Jozef





On Thu, Apr 3, 2014 at 11:24 AM, Andy Smith <the4thamig...@googlemail.com>wrote:

> Thanks Josef, but could you explain a bit more. Are you saying that the
> operation of replacing a substring (by index & length) with another
> substring is not a common operation?
>
> i.e.
>
> (defn replace-substring [s r start len] (str (subs s 0 start) r (subs s (+
> len start))))
>
> If so, that does suprise me. I think I can better understand guns
> objection on the basis that it would be a bad function for an immutable
> string library, since the naming suggests mutability and also that if you
> wanted to replace multiple substrings (which each would require several
> copy operations) it would be (I think?) more efficient to do it in a single
> expression involving multiple calls to substring, than using
> replace-substring. But even so, there is already the function 'replace' in
> clojure which also suggests mutability.
>
> However, not being from a a java background I was also quite surprised to
> find out that there isnt a similar function in java (
> http://stackoverflow.com/questions/14642978/replace-part-of-a-string-between-indexes-in-java
> ).
>
> Im also interested in your second comment and was wondering what you mean
> by transient string?
>
> Thanks
>
> Andy
>
>
>
>
>
> On Wednesday, 2 April 2014 19:05:48 UTC+1, Jozef Wagner wrote:
>>
>> No. IMO this is not a common operation and should not be in core. If you
>> need do it a lot, you should not use java string in the first place.
>>
>> What should be included in core is a transient string, with support for
>> assoc!.
>>
>> Jozef
>>
>>
>> On Wed, Apr 2, 2014 at 7:49 PM, Andy Smith <the4th...@googlemail.com>wrote:
>>
>>> just a shame its not in the core, no?
>>>
>>>
>>> On Wednesday, 2 April 2014 18:06:03 UTC+1, A. Webb wrote:
>>>>
>>>> Using subs (no need for join) is the way I would go, just define
>>>>
>>>>
>>>>     (defn replace-at [s n c] (str (subs s 0 n) c (subs s (inc n))))
>>>>
>>>>     (replace-at "hello" 1 "a") ;=> "hallo"
>>>>
>>>> and carry on.
>>>>
>>>>
>>>>
>>>  --
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> ---
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to