Yesterday I showed you how we made the first two tests pass. And I also told you that Per Dervall helped to solve the rest. I asked the question on StackOverflow. And I also pinged him about this on twitter.
And the poor man made an effort to respond in VB.Net.
And in short, this is the result.
```vbnet Public Class ParseLatinPlantName
Public Function Parse(ByVal name As String) As Plant
Dim config = ParserFactory.Fluent()
Dim expr = config.Rule()
Dim subSpecies = config.Rule()
Dim hybridIndicator = config.Expression
hybridIndicator.ThatMatches("x").AndReturns(Function(f) f)
Dim sp = config.Expression()
sp.ThatMatches("sp.").AndReturns(Function(f) f)
Dim name1 = config.Expression()
name1.ThatMatches("w+").AndReturns(Function(f) f)
Dim nothing1 = config.Rule()
expr.IsMadeUp.By(name1).As("Genus") _
.Followed.By(name1).As("Species") _
.Followed.By(subSpecies).As("Subspecies") _
.WhenFound(Function(f) New Plant With {.Genus = f.Genus, .Species = f.Species, .SubSpecies = f.Subspecies}) _
.Or.By(name1).As("FirstSpecies").Followed.By(hybridIndicator).Followed.By(name1).As("SecondSpecies") _
.WhenFound(Function(f) New Plant With {.IsHybrid = True})
subSpecies.IsMadeUp.By(sp).Followed.By(name1).As("Subspecies").WhenFound(Function(f) f.Subspecies) _
.Or.By(nothing1)
Dim parser = config.CreateParser()
Dim result = DirectCast(parser.Parse(name), Plant)
Return result
End Function
End Class```
And here is the C# code.
```csharp public Plant Parse(string input) { var config = ParserFactory.Fluent(); var expr = config.Rule(); var subSpecies = config.Rule(); var hybridIndicator = config.Expression(); hybridIndicator.ThatMatches(“x”).AndReturns(f => f);
var sp = config.Expression();
sp.ThatMatches("sp\.").AndReturns(f => f);
var name1 = config.Expression();
name1.ThatMatches("\w+").AndReturns(f => f);
var nothing1 = config.Rule();
expr.IsMadeUp.By(name1).As("Genus")
.Followed.By(name1).As("Species")
.Followed.By(subSpecies).As("Subspecies")
.WhenFound(f => new Plant {Genus = f.Genus, Species = f.Species, SubSpecies = f.Subspecies})
.Or.By(name1).As("FirstSpecies").Followed.By(hybridIndicator).Followed.By(name1).As("SecondSpecies")
.WhenFound(f => new Plant {IsHybrid = true});
subSpecies.IsMadeUp.By(sp).Followed.By(name1).As("Subspecies").WhenFound(f => f.Subspecies)
.Or.By(nothing1);
var parser = config.CreateParser();
var result = (Plant) parser.Parse(input);
return result;
}
}```
I won’t repeat the explanation here, I will leave that on SO.
But I did a few performance tests. Nothing very official. Just good to know.
csharp
[Test]
public void SpeedTest()
{
var parser = new ParseLatinPlantName();
Plant result;
for(int i =0; i < 10000; i++)
{
result = parser.Parse("Salvia x jamensis");
}
}
Ncrunch tells me the for loop takes 20.717 seconds.
And then I did this.
csharp
var parser = new ParseLatinPlantName();
Plant result;
for(int i =0; i < 10000; i++)
{
result = parser.Parse("Salvia x jamensis");
}
for (int i = 0; i < 10000; i++)
{
result = parser.Parse("Salvia jamensis");
}
for (int i = 0; i < 10000; i++)
{
result = parser.Parse("Salvia jamensis sp. something");
}
The first for takes around 20 seconds the second around 25 and the third around 13 seconds.
I let you draw your own conlcusions on why that is.
I think Piglet is very cool and can be useful The fluent code is very readable. The biggest problem so far is a lack of documentation. But it can only get better.