Alex gave you a correct (but fairly short) answer. I’d like to expand on it a 
bit, partly in light of a certain recent blog post, partly because of a 
personal “hot button”…

This is going to be along the same lines as clojure.set functions producing 
“garbage” output if you give them “garbage” input (not sets). This is the 
classic computer science “undefined” behavior that we see in many other 
languages, where the behavior is only defined for the specific types of inputs.

I would _love_ all the clojure.string functions to be defined for nil as an 
input – since we have (str nil) => “” – but adding that nil check, or even 
calling str directly in clojure.string functions, adds quite an overhead for 
all uses (so that proposal would never be accepted).

Looking at the clojure.string namespace docstring, it is explicit about nil 
arguments:

“passing nil will result in a NullPointerException unless documented otherwise.”

This makes me sad ☺ It’s almost my only source of NPEs in my Clojure code and I 
pretty much always want the empty string behavior in case of nil. Oh well.

The docstring also has this to say about argument types:

“When a function is documented to accept a string argument, it will take any 
implementation of the correct *interface* on the host platform. In Java, this 
is CharSequence, which is more general than String. In ordinary usage you will 
almost always pass concrete strings.”

That explains why it calls toString() – to convert CharSequence (or any of its 
implementations) to String. Unfortunately, much as with clojure.set functions, 
if you pass any argument that is not an implementation of CharSequence but 
happens to support toString() – which is nearly anything – then you get 
“garbage” out because you passed “garbage” in.

I think everyone passes a non-string value to a clojure.string function at 
least once and then scratches their head at the bizarre result (which often 
pops up a long way down the chain of string manipulation and therefore some 
distance from the bug).

It’s the price we pay for improved performance in the “correct” use cases ☹

As for blank? Yes, that seems like the docstring needs correcting since it 
returns “True if s is falsey (nil or false), empty, or contains only 
whitespace.”

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood


On 6/21/16, 11:24 AM, "Elena Machkasova" <clojure@googlegroups.com on behalf of 
ele...@morris.umn.edu> wrote:

Greetings,

I was looking at clojure.string functions, and noticed that some have 
unexpected (especially for less experienced programmers) behavior on non-string 
arguments. For instance, 'capitalize' applies toString to its argument, 
effectively making it possible to pass any type, but with unexpected results. 
Here are some examples that may be really confusing to novices, especially 
since it's not immediately obvious that the argument is returned as a string 
when it's printed back:

(str/capitalize [\a \B \c]) ; returns "[\a \b \c]"
(str/capitalize (char-array "aBc")) ; returns the address, as a string

Interestingly, 'reverse' doesn't allow non-string arguments since it uses a 
StringBuilder, and not toString, to create a string, and there are a few other 
clojure.string functions that behave like 'reverse' in this regard. As a 
minimum, this is inconsistent with 'capitalize'. 

As a separate issue, blank? returns 'true' when passed 'false' (since the check 
is for false, not specifically for nil), but (blank? true) is a type error. 

It is fairly easy for experienced programmers to understand what's going on by 
reading the source code, but none of these behaviors are documented, and would 
confuse beginners.  

Is there anything that I am overlooking in these design decisions, or should 
this implementation be changed? 

Thanks!

Elena 
-- 
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