String.Empty Field

What is the problem with ""? emptyList(), emptyMap are different. There isn’t any other way to get what they provide since they are backed by a special implementation of List, Map also there isn’t a literal you can use for them. We don’t use Int.Empty or Int.Zero either.


That all said if you need a function/property for this for any reason feel free to add this to your project. I just don’t see any reason why we need this in the standard library.

3 Likes

Maybe slightly off topic, but why do you need emptyMap()?

This seems to have the same result:
val myEmptyMap = mapOf<Int, Int>()

The problem with “” that you cannot use it with string interpolation, you have to define variable or function. We don’t have Int.Zero but Java provides BigDecimal.Zero, BigDecimal.One, and even BigDecimal.Two. I understand need for Zero and One, but I don’t see any reason for Two, nevertheless someone saw the reason and added it. Why it is that big deal to have field or function to represent empty string?

It doesn’t matter do you need the function emptyMap() or not, it already exists.

I personally prefer to follow declarative style of programming saying what I want to have or to do instead of imperatively defining how it should be done. This is why I prefer to use emptyList() instead of listOf().

Sure you can. Out of the box. Replace emptyString() with “” in your last example. It will work.

3 Likes

I think String.Empty is nice to have, imagine that you are trying to return an empty string in some cases in your code like:
val studentSecretName = if(student.tellMySecretName)student.secretName else “”
what if someone accidentally edited it with any string value

I would love to see String.EMPTY or equivalent, I agree with @ peteski, it makes the intention clear…

Strings in Java can be created different ways, one of which is using String constructor. For example like this:

var x = new String("");
var y = new String("");
System.out.println(x == y); // will print false

var a = "";
var b = "";
System.out.println(x == a); // will print false
System.out.println(x == b); // will print false
System.out.println(a == b); // will print true

Why wouldn’t it work?

fun main() {
    val firstName = "First" 
    val middleName = null
    val lastName = "Last" 
    val fullName = "$firstName ${middleName ?: ""} $lastName"
    println(fullName) 
} 

Yes, there are cases when strings are for example created by parsing some data, so empty string is not created from a literal. But in these cases String.EMPTY would be also not used, so I don’t see your point. Maybe I’m wrong, but I believe performance-wise String.EMPTY and just "" are exactly the same.

3 Likes

This thread is about simple request to add language feature to represent an empty string.
So far all arguments against this can be downed to simple statement: “you don’t need it”.
I would like to hear real argument, why this cannot be done?
Will this new addition affect compiler performance? Will it affect application performance? Or maybe it will complicate String processing during compile or runtime? Something? Anything?

Yes and sometimes this is just enough, sometimes less is more. I’m not that much against String.EMPTY, I don’t have a strong opinion about it, but I think your argument is not valid. We don’t add new language features just because we can. Usually, we need good reasons to do it and KEEPs pretty often start with a question: “Do we really need this feature in the language/stdlib itself?”. Otherwise, we end up with messy language and messy code where some developers use String.EMPTY and some use "". And some even use '' as they got used to apostrophes in their favorite language X, so they requested it in Kotlin and it was approved because “why not”.

Still, I think we miss possibility to add extensions to classes that don’t have a companion. With it we would be able to create String.EMPTY in our project if we want.

1 Like

@peteski gave really good argument and I complete agree with it: the reason for having language feature to represent an empty String is to make intent of the code more clear.
For example Kotlin have 2 functions: listOf() and emptyList(). When I see code like listOf() it not always obvious what this means, is it suppose to create an empty list or is this just possible typo/bug? With emptyList() there is no ambiguity in its use.
Same with "", its usage is not always clear. It maybe some typo or bug, you cannot be sure. If language will offer something similar to represent an empty String be it constant or static method, the use of this feature will make intention of the code clear.

For me an argument like “you can create your own constant or method” sounds like an excuse not a real argument, because we could’ve lived without for example emptyList() function, but language provides it for us. Why not create similar for String?

Here are three reasons why this proposal makes me uneasy. (None is decisive, but for me they all add up.)


Length

listOf()emptyList() is a 37½% increase in length.

But ""String.empty is a 600% increase!

Conciseness isn’t the most important factor in any language, of course; but it’s one of the major factors in making Kotlin such a pleasure to read and write, and a named constant reduces that.

Familiarity

"" is used in just about every programming language that has strings. String.empty is not; in fact, I don’t think I know any that do.

And that unfamiliarity leads to confusion. Most JVM developers will know that string constants get inlined. But most won’t know how any String.empty is implemented. It is opaque. Does it return the same constant each time? (If so, what’s the point of it?) Or can it create new ones in some or all cases (e.g. a thread-local instance)? Does it do any processing? (After all, being Kotlin, it could call an arbitrarily-complex getter method.)

Consistency

The more alternatives there are, the more likely it is that the code I write will be different from the code you write. That makes it (very slightly) harder for us to read each other’s code; and to teach the language because there are more alternatives to cover; and to recognise similarities in different-looking code; and generally to share and maintain code.

As a counter-example, Perl has a deliberate policy of providing multiple approaches; in fact, its motto is ‘There’s More Than One Way To Do It!’. That arguably led to everyone writing in their own personal dialect, giving it a reputation as an impenetrable Write-Only Language and maybe even contributing to its waning popularity as compared with e.g. Python. I don’t want to see Kotlin taking even tiny steps down that road.


One of the arguments for a named constant is that hard-coded literals are bad. And in general, they are (or at least, are a code smell). But for me, the empty string is a special case; it’s so ubiquitous, so widely used and understood, and so obvious, that its intent is perfectly clear, and the risk of confusion or typos negligible. And due to string constant inlining, it has no performance issues; nor does it need localising or translating or white-labelling.

Of course, this is a very small proposed change, and not worth getting heated up over. (Maybe that’s why we’re bike-shedding here!) But I think it illustrates the need for a Minus 100 Points approach to language design. Kotlin’s designers haven’t been afraid to add major features where their benefits outweigh the added complexity. But they’ve also shown taste in knowing what to leave out, so that the language’s ‘complexity budget’ is well-spent. And for me, the benefits of this particular proposal seem nebulous and far from outweighing the points above.

2 Likes

As @nbness1337 said, you can define String.empty yourself, like so:

val String.Companion.empty
    get() = ""

Then you can use String.empty in your code instead of emptyString():

val fullName: String = "$firstName ${middleName ?: String.empty} $lastName"

That being said, the majority of people will never use String.empty or even know it exists; there’s no reason to confuse them and add String.empty to the standard library (especially when most languages don’t have it) when the language allows you to add it yourself.