## strong: Makes strings stronger (1.0.2)

BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

### strong: Makes strings stronger (1.0.2)

I've been wanting some of the awesome features of Ruby's String class for a little while now in Lua. So this morning and last night, I created a library which I've called "strong".

GitHub repo: https://github.com/BlackBulletIV/strong
Documentation: https://github.com/BlackBulletIV/strong/wiki
Project page on my website: http://nova-fusion.com/projects/lua/strong
Wiki page: http://love2d.org/wiki/strong

Video demonstration of some features:
Last edited by BlackBulletIV on Thu May 12, 2011 4:17 am, edited 9 times in total.

kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Contact:

### Re: strong: Makes strings stronger

BlackBulletIV wrote:I've been wanting some of the awesome features of Ruby's String class for a little while now in Lua.
Needless to say, I like the idea and the name.
BlackBulletIV wrote:Working on creating the tests which make sure everything works. I'm rapidly making things work as they should.
I don't like this part so much. If I've learned something, is that making tests first helps. A lot!

I actually tried both approaches with inspect (see this commit and the next one). The result was: implementing the test first was both easier and ... wait for it ... faster to do!

Because doing the tests first is more fun !

Testing stuff the "traditional way" (i.e. opening a lua console, importing your lib, and executing functions) is quite boring, at least for me. I found myself procrastinating, browsing the internet etc, instead of doing the tests I was supposed to be doing.

When you write the tests first, you are actually programming. It's something creative, I enjoy it, and I don't feel tempted to do other stuff. Running the tests takes 2 keystrokes and lasts milliseconds. They pass or they don't. And then, back to programming! The "boring time" is reduced.
When I write def I mean function.

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

### Re: strong: Makes strings stronger

Your implementation of string.insert seems a bit... inefficient to me.

I'd do something like:

Code: Select all

function string:insert(index, other)
index = index % (#self+1)
if index == 1 then
return other .. self
elseif index == 0 then
return self .. other
else
return self:sub(1, index - 1) .. other .. self:sub(index)
end
end
Didn't test it, but it should work. It handles negative indices as well.

EDIT: position of insertion

Code: Select all

---------------------
| A | B | C | D | E |
---------------------
1   2   3   4   5   6
-5 -4  -3  -2  -1   0

BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

### Re: strong: Makes strings stronger

kikito wrote:Needless to say, I like the idea and the name.
Thanks kikito!
kikito wrote:I don't like this part so much. If I've learned something, is that making tests first helps. A lot!

I actually tried both approaches with inspect (see this commit and the next one). The result was: implementing the test first was both easier and ... wait for it ... faster to do!

Because doing the tests first is more fun !

Testing stuff the "traditional way" (i.e. opening a lua console, importing your lib, and executing functions) is quite boring, at least for me. I found myself procrastinating, browsing the internet etc, instead of doing the tests I was supposed to be doing.

When you write the tests first, you are actually programming. It's something creative, I enjoy it, and I don't feel tempted to do other stuff. Running the tests takes 2 keystrokes and lasts milliseconds. They pass or they don't. And then, back to programming! The "boring time" is reduced.
Of course you don't like it . I'm not a TDD person by any means, I don't write tests much, but in this case I thought they were necessary for finding problems (and there's quite a few that have been found already). I find I have to force myself to write tests, I just find it boring. But maybe it would be different if I did tests first for the purpose of designing an API, I don't know.

I find the problem is, most of the time you write more test code than application code when using tests. So as an analogy, a builder places a brick down, which takes a minute. He then spends 5 minutes inspecting that he placed it correctly. So he ends up spending an hour laying bricks, and 5 hours checking that he didn't do anything wrong.

But anyway, I think I'm just put off by TDD because I've been doing it the exact opposite for some time now. Do you know any good way to get yourself into TDD? I guess this is same kind of ordeal I had with two-space indentation, I knew it was better (because I was coding in Ruby now), but I just couldn't get over not having four spaces; I ended up forcing myself to "get used to it", and now my eyes have adjusted and I can't stand using four spaces (except when I'm in a curly braced language, then I'm not sure what to do).

Anyway, enough rants from me.

--------------------------------

As for your post Robin, thanks heaps! I've put it in the repo and marked your kindness in the README .

kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Contact:

### Re: strong: Makes strings stronger

BlackBulletIV wrote:Do you know any good way to get yourself into TDD?
The beaten path is the best one IMHO. Very succintly:
• Pick a small enough problem (strong is an excellent candidate)
• (This is optional, but surprisingly useful) - write the README of the library. Make sure it includes some example, or the names of the methods you will use. Some people jokingly call this "README-driven development".
• Build up the "blank state" (so you are able to run the tests, even if there are no tests yet, without errors). In lua this usually means something like making a return {} on your main <library>.lua file, and making sure that you are able to require that file from inside the test_<mylib>.lua file (or spec_<mylib>.lua). As we have talked over email, I've found that in Lua the simplest solution for this is using symbolic links for the lib files/folders inside the tests folder.
• Pick one method (or independent piece of functionality) for the lib. For example, the __index metamethod for strings.
• Write a test for the simplest case of that method. For example, __index with a number only.
• Make sure that the test fails. I mean, actually going to the console and making sure that the test fails properly - this makes sure that you have not, for example, made a syntax error on the test code.
• Write just the minimum amount of code for making that test pass. This requires you to think like a programmer, not like a code monkey. For example, if your test does ("hello")[1], you don't have to make the index method return "h" on your test. You can actually skip the very very obvious steps and make it return self:sub(key, key)
• Make sure that the test pass.
• Add more tests, make them fail, implement them, and pass the tests again, until the functionality of that first method is complete (in the index case, numbers and not-numbers) and the edge cases have been discovered (what happens when a negative number is passed? what about nil? a function?)
• Then move over to the next piece of functionality and start with the simplest case again.
This might sound like a lot of work, but take into account that running the tests is super easy - In my case, it takes more time to save the file than to run the tests (because I use the mouse). You will discover soon enough that once you get into the flow, it's more satisfying than the "usual" way.
When I write def I mean function.

BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

### Re: strong: Makes strings stronger

Thanks for that kikito. I'll give it a try. Maybe I should create a library or two to "learn" TDD (just like you did to test TDD in Lua).

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

### Re: strong: Makes strings stronger

Another version of string.insert, which is more consistent in regard to negative indices, at the expense of slightly less elegant code:

Code: Select all

function string:insert(index, other)
index = (index < 0 and index + 1 or index) % (#self+1)
if index == 1 then
return other .. self
elseif index == 0 then
return self .. other
else
return self:sub(1, index - 1) .. other .. self:sub(index)
end
end

Code: Select all

---------------------
| A | B | C | D | E |
---------------------
1   2   3   4   5   6
-6 -5  -4  -3  -2  -1

BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

### Re: strong: Makes strings stronger

Thanks for that. I've put it in .

EDIT: Added this a library in the wiki.

BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

### Re: strong: Makes strings stronger

Ok here's the status of strong.

Pretty much all methods are implemented (I think the 'center' method would be the only one left) and have tests for them. If you look at the README in the Bugs/Problems section you'll find the details for a pesky problem in the squeeze method. This problem is the reason I'm hesitant to make a 1.0 release now. If anyone could help out, that would be most appreciated.

I've also started working the documentation, have a look at the GitHub wiki for that. If anyone would like to help out in the function reference, please do.

Finally I want your opinion on a couple of things.

First is whether I should use camel-case naming for the functions with multiple words, or whether I should keep their Ruby names which have underscores? And no, I won't accept the Lua style of all lower-case, and no spaces; that's hard to read (and I don't know why they did that in the first place).

And second is whether I should use function arguments for iterative methods, like bytes, chars, and eachLine, or use iterators? I've tending to like iterators more, as it's more Lua-like.

Thanks guys!

Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

### Re: strong: Makes strings stronger

You have no string.title(), right?
BlackBulletIV wrote:And second is whether I should use function arguments for iterative methods, like bytes, chars, and eachLine, or use iterators? I've tending to like iterators more, as it's more Lua-like.
Definitely make them iterators.

table.foreach and table.foreachi are deprecated in favour of pairs and ipairs.