I really like these advanced bits, they’re great. I’d like it if they went a bit more in-depth, though. You apologize for going on a tangent and I don’t think you should apologize at all haha. They’re optional anyway.
One thing I’d like to see explained a bit more are the square brackets (for other students reading this) in front of the lambda and what they mean. I’ve taken the liberty to write something up in here, but since I am also just a student please correct me if I’m wrong.
Two notes before reading my code snippets:
- Where the lesson uses
Isograms
I have usedWords
. - Similarly, where the lesson uses
IsIsogram
I have usedValidateWord
.
Let’s gooo:
The square brackets mean “capture”. As in “capture these variables from the scope and make them available inside of the lambda”. I don’t know what it actually does and what type of class it generates (I assume they become member variables) but I do know that by adding for example this
to the capture list, it allows you to use instance methods inside of the lambda. So:
FFileHelper::LoadFileToStringArrayWithPredicate(Words, *WordListPath, [this](const FString& Word) { return ValidateWord(Word); });
I also found that adding an &
works because it captures all available variables in the reaching scope (the method in which the lambda is being created) by reference. Something I am unsure about but think is the case is that this includes this
and anything else that is available. It basically copies the current scope into the lambda:
FFileHelper::LoadFileToStringArrayWithPredicate(Words, *WordListPath, [&](const FString& Word) { return ValidateWord(Word); });
And the same applies to the equals sign (=) which works, but instead of a reference passes in a value (or copy) of everything that is available:
FFileHelper::LoadFileToStringArrayWithPredicate(Words, *WordListPath, [=](const FString& Word) { return ValidateWord(Word); });
While I’m at it, you can also pass in specific values to capture. In this example I’ve taken the 4 and 8 from the lambda and instead of using them inline, I pass them in as a variable reference:
int MinLength = 4;
int MaxLength = 8;
FFileHelper::LoadFileToStringArrayWithPredicate(Words, *WordListPath, [&MinLength, &MaxLength](const FString& Word)
{
return Word.Len() >= MinLength && Word.Len() <= MaxLength;
});
Without an ampersand in front of the variable ([MinLength, MaxLength]
instead of [&MinLength, &MaxLength]
), the capture behaviour defaults to a value capture (copy). There’s more you can do with captures (for example [=, &MaxLength]
which means everything by value except for MaxLength
which would be by reference) but I think this covers the basics and also explains why we’re using a static method in the lesson, and how we could (if we wanted to) avoid using a static method.MaxLength
Again please let me know if I made a mistake in here. The main purpose of sharing this is to help me remember how this stuff works.