How to return Error Message from assertion in Kotlin - assert

I am getting comfortable in Kotlin after switching from Java and could not find out how to use Kotlin's assert function in conjunction with an error message.
Sounds simple, I just need something similar to Java's
assert count > 5 : "value too small"
I tried
assert(count > 5, "value too small")
However, the second argument needs to be () -> Any. How to achieve that?

assert's message parameter is not a String, but a function returning a String. This is so because otherwise, since assert is a normal Kotlin function, its arguments would be evaluated every time which would lead to unnecessary overhead (and sometimes change in semantics) of calculating the message string in case that string is a complex expression.
To pass a function argument, use the lambda syntax. The last argument which is a lambda may be left out of the parentheses:
assert(count > 5) { "value too small" }

I got it by myself, I need to declare a lambda function without parameters, which looks like this in Kotlin:
assert(count > 5, {"value too small"})
assert(count > 5, { -> "value too small"})
Sorry for bothering you! I leave the question, maybe some other beginner will find it useful.

Related

How to search by member accessor value with std::find_if()?

I am learning C++ at the moment and have an example program implemented with an array of objects data store. To make some other operations easier, I have changed the store to a vector. With this change I am now not sure of the best way to search the store to find an object based on a member accessor value.
Initially I used a simple loop:
vector<Composer> composers; // where Composer has a member function get_last_name() that returns a string
Composer& Database::get_composer(string last_name)
{
for (Composer& c : composers)
if (c.get_last_name().compare(last_name))
return c;
throw std::out_of_range("Composer not found");
}
This works just fine of course, but to experiment I wanted to see if there were vector specific functions that could also do the job. So far I have settled on trying to use find_if() (if there is a better function, please suggest).
However, I am not sure exactly the correct way to use find_if(). Based on code seen in online research I have replaced the above with the following:
vector<Composer> composers; // where Composer has a member function get_last_name() that returns a string
Composer& Database::get_composer(string last_name)
{
auto found = find_if(composers.begin(), composers.end(),
[last_name](Composer& c) -> bool {c.get_last_name().compare(last_name);});
if (found == composers.end())
throw out_of_range("Composer not found");
else
return *found;
}
This does not work. It does find a result, but it is the incorrect one. If an argument that matches, say the third composer's last name the function always returns the first item from the vector (if I pass an argument that doesn't match any last name the function correctly throws an exception)... what am I doing wrong?
You are on the right track, your lambda needs return statement. Also in such case you do not have to specify it's return type explicitly, it can be deduced:
find_if(composers.begin(), composers.end(),
[last_name](const Composer& c) { return c.get_last_name() == last_name);});
you original code should not compile or at least emit warning(s), you should pay attention to them.
Note: it is not clear how your original code worked if you tested it, it should be:
if (c.get_last_name().compare(last_name) == 0 )
or simply:
if (c.get_last_name() == last_name )
as std::string::compare() returns int -1 0 or 1, so your code searches for string that does not match variable last_name
With range-v3, you may use projection:
auto it = ranges::find(composers, last_name, &composers::get_last_name);

Paramter pack unfolding correctly to initialize a std::array of std::strings

currently i am playing around with parameter packs in c++. I have wrote this little snippet:
template<typename ...Targs>
auto toString(Targs... args) -> std::array<std::string,sizeof...(Targs)>
{
return {
{
(std::forward<std::string>(std::to_string(args)),...)
}
};
}
It has no real purpose but the exercise was/is to create an array of strings from the given parameter which can vary in count and type.
What I hoped to achieve was to do the following:
std::array<std::string,3> SomeName = { {std::to_string(1),std::to_string(2),std::to_string(3)} };
but more generic. That was the idea for the toString function. Unfortunately the result I get is not what I expected. The returned std::array will only contain the last parameter given to toString with the rest of the strings being empty.
But what I actually expected was that each argument given to toString gets converted into an string and put into the element of the array.
What did I miss about parameter pack unfolding? Or do I have just annoyingly stupid mistake?
You have an extra comma:
(std::forward<std::string>(std::to_string(args)),...)
// ^
This now becomes a fold expression over a comma, which is a single expression that gives you one string, where you want N strings. Also, the term isn't unfolding, the term is parameter pack expansion.
Removing the comma gives you what you want:
return {{std::to_string(args)...}};
Note that the std::forward<> is unnecessary - so I removed that too.

C++ using std::accumulate to generate a map<int,int>

I have a problem creating a std::map<int, int> from a vector of pointers, called files. Each pointer points to an object with three member variables, one of which is size of type int. The key of the map would be the size and the value would be the number of objects which have the same size.
Do NOT waste your time on the second one! It is the next step in my program and I have figured it out already, I think. For initialization of the map I am using std::accumulate, because it returns a value. I am using std::tr1::shared_ptr for the pointers and a lambda expression for the predicate function. I am having problems with compilation.
Here's the code snippet:
map<int,int>* sizes = new map<int,int>();
sizes = accumulate(files.begin(), files.end(),sizes,
[&sizes](map<int,int> acc, shared_ptr<CFileType>& obj)
{
return sizes->insert(pair<int,int>(obj->getSize(),0));
});
Here's the error:
error C2664: 'std::pair<_Ty1,_Ty2> `anonymous-namespace'::::operator ()(std::map<_Kty,_Ty>,std::tr1::shared_ptr &) const' : cannot convert parameter 1 from 'std::map<_Kty,_Ty> ' to 'std::map<_Kty,_Ty>'
I am not very sure what to pass to the lambda function. I have tried with pair<int, int>, but it didn't work. Also, I must mention that this map is returned to another function, so it has to be a pointer.
Any help from you would be appreciated. Thanks!
UPDATE:
Problem solved, here is the solution:
map<int,int>* sizes = accumulate(files.begin(), files.end(), new map<int,int>(),
[](map<int,int>* acc, shared_ptr<CFileType>& obj)->map<int,int>*
{
acc->insert(pair<int,int>(obj->getSize(),0));
return acc;
});
The error message is that you have a type mismatch between the two kinds of std::maps. It looks like the error is in the code that calls the lambda, which apparently passes the wrong thing for the acc parameter. The good news is that the lambda, as posted, never actually uses the acc parameter.

C/C++ Syntax - Separating statements with , instead of ; legal?

I just ran into this piece of code that does this :
delete a, a = 0;
It compiles and runs just fine. But isn't this supposed to be :
delete a;
a = 0;
Why is separating statements using , allowed in this case ?
Thanks :)
In C and C++, most "statements" are actually expressions. The semicolon added to an expression makes it into a statement. Alternatively, it is allowed (but almost always bad style) to separate side-effectful expressions with the comma operator: the left-hand-side expression is evaluated for its side-effects (and its value is discarded), and the right-hand-side expression is evaluated for its value.
This is the comma-operator. It evaluates both it's arguments and returns the second one.
This is the comma operator. It can be used to separate expressions, but not declarations.
That is comma operator. MSDN article is here. And have a look at this question to understand how it works.
While it is possible to write code like that, it may be somewhat weird. A slightly more realistic usecase would be if you have a struct T as follows:
struct T {
bool check() const;
void fix();
};
Now you want to iterate through everything in the struct and run check on it, and then call fix if check returns false. The simple way to do this would be
for (list<T>::iterator it = mylist.begin(); it < mylist.end(); ++it)
if (!it->check())
it->fix();
Let's pretend you want to write it in as short a way as possible. fix() returning void means you can't just put it in the condition. However, using the comma operator you can get around this:
for (auto it = mylist.begin(); it != mylist.end() && (it->check() || (it->fix(), true)); ++it);
I wouldn't use it without a particularly good reason, but it does allow you to call any function from a condition, which can be convenient.

boost lambda collection size evaluation

I have a function of the form:
void DoSomething(const boost::function<bool ()>& condition, other stuff);
This function does some work and returns only when the condition is true. The condition has been expressed as a functor argument because I want to supply different conditions at different call sites.
Now, this is fairly straightforward to use directly, but it requires declaring lots of little throwaway functions or functor objects, which I'd like to avoid if possible. I've been looking at Boost's lambda library for possible ways to do away with these, but I think I'm missing something fundamental; I just can't get it to do what I want.
One case that's stumped me at the moment: I have a std::vector collection called data; the condition that I'm after is when the size() of that collection reaches a certain threshold. Essentially, then, I want my condition functor to return true when data.size() >= threshold and false otherwise. But I've been having trouble expressing that in lambda syntax.
The best that I've been able to come up with thus far (which at least compiles, though it doesn't work) is this:
boost::function<bool (size_t)> ge = boost::bind(std::greater_equal<size_t>(),
_1, threshold);
boost::function<size_t ()> size = boost::bind(&std::vector<std::string>::size,
data);
DoSomething(boost::lambda::bind(ge, boost::lambda::bind(size)), other stuff);
On entry to DoSomething, the size is 0 -- and even though the size increases during the course of running, the calls to condition() always seem to get a size of 0. Tracing it through (which is a bit tricky through Boost's internals), while it does appear to be calling greater_equal each time condition() is evaluated, it doesn't appear to be calling size().
So what fundamental thing have I completely messed up? Is there a simpler way of expressing this sort of thing (while still keeping the code as inline as possible)?
I'd ideally like to get it as close as possible to the C# equivalent code fluency:
DoSomething(delegate() { return data.size() >= threshold; }, other stuff);
DoSomething(() => (data.size() >= threshold), other stuff);
The problem is, that the lambda function stores a copy of the data vector, not a reference. So size() is called on the copy, not the original object that you are modifying. This can be solved by wrapping data with boost::ref, which stores a reference instead:
boost::function<size_t ()> size = boost::bind(&std::vector<std::string>::size,
boost::ref(data));
You can also use the normal >= operator instead of std::greater_equal<> in the definition of your lambda function and combine it all together:
boost::function<bool ()> cond =
(boost::bind(&std::vector<std::string>::size, boost::ref(data))
>= threshold);
DoSomething(cond, other stuff);