I like Ruby's string multiplication so I thought I'd see if I could do it in Swift. I came up with these implementations:
@infix func * (left: String, right: Int) -> String {
var result = ""
for _ in 0..right {
result += left
}
return result
}
operator infix ** {}
@infix func ** (left: String, right: Int) -> String {
return Array(count: right, repeatedValue: left).reduce("", +)
}
println("Andrew rules! " * 42)
println("Andrew rules! " ** 42)
Anyone have improvements or other implementations?
1 Answer 1
As Flambino points out, the method is very problematic for negative integers.
You need to either change the function to only accept unsigned integers or come up with some solution that makes sense for negative numbers.
In general though, I don't particularly like operator-overloading. Using functions/methods means there's some plain-English name to the operation you're performing that will give me some sort of hint at what the operation does so I don't have to guess.
As someone coming from an Objective-C/Foundation background (which will likely be most Swift programmers) and having zero Ruby experience, I could maybe guess at what the first one does:
println("Andrew rules! " * 42)
But as for the second one?
println("Andrew rules! " ** 42)
I'd have absolutely no clue. And I doubt I'd be the only one.
The amount of time you save typing **
instead of a more descriptive function name (which the IDE will autocomplete for you meaning the amount of time is basically the same either way) is definitely not worth the amount of time that other programmers behind you take to go figure out what this does:
let myVar = "Hello world!" ** 27
There's not even the slightest hint as to what this returns, and there's no descriptive function name to give any clues... so now I have to go hunt down where ever you've put the operator overload function for a string/int.
-
1\$\begingroup\$ Is there an explanation for the downvote on this answer? I think the review here is reasonable enough and doesn't warrant it, from what little Swift I know. \$\endgroup\$syb0rg– syb0rg2014年06月20日 22:59:20 +00:00Commented Jun 20, 2014 at 22:59
-
\$\begingroup\$ Your "review" consists of little more than a rant against operator overloading. \$\endgroup\$200_success– 200_success2014年06月20日 23:13:14 +00:00Commented Jun 20, 2014 at 23:13
-
3\$\begingroup\$ It's not a rant. It's a perfectly valid reason to avoid overdoing operator overloading. The first operator does exactly what I'd expect it to. The second one, I guess, does what it does in Ruby, but someone without a Ruby background has no clue. Readability is a perfectly valid thing to review on CodeReview, and that's what I've reviewed. I feel the
**
drastically decreases the readability. \$\endgroup\$nhgrif– nhgrif2014年06月20日 23:18:04 +00:00Commented Jun 20, 2014 at 23:18 -
\$\begingroup\$ That
**
isn't something taken from ruby, it's just an alternative implementaton for*
, likeimplementation1
andimplementation2
. That actually proves your point because you have to descipher the code to see that both methods do the same thing. \$\endgroup\$Sulthan– Sulthan2014年06月21日 16:06:50 +00:00Commented Jun 21, 2014 at 16:06 -
\$\begingroup\$ @Sulthan is correct. I only used
**
so that I could compare implementations. Sorry for the confusion. \$\endgroup\$Andrew Moore– Andrew Moore2014年06月23日 13:50:35 +00:00Commented Jun 23, 2014 at 13:50
join("", Array<String>(count: right, repeatedValue: left))
\$\endgroup\$*
operator is that it won't complain about receiving a negative multiplier. Change to aUInt
maybe? (I have ~10 minutes experience with Swift so far, so I'm partly guessing) \$\endgroup\$"Andrew Rules" * 0
return an empty string? Ruby's does. Since you're mimicking that operator, so should yours. \$\endgroup\$