I have the following higher-order function:
public function function Method (required string name, args=[]) {
return function (object) {
return invoke(object, name, args);
};
}
Example use:
['abc', 'defg'].map(Method('len')); // [3, 4]
Unfortunately, that example is broken. When the first argument to invoke is a string, it is interpreted as the name of a component. Is there a way of implementing Method that avoids this problem?
Related
I have a custom list class capable of storing recursive lists. There is a json file that is parsed during runtime which will contain information about what functions to call on what lists. I am using nlohmann::json library
For example:
class Game{
CustomListElement setup;
}
class CustomListElement{
CustomListElement getElementAt(std::string){
//returns element
}
CustomListElement upfrom(int start){
//create CustomList from int
}
}
This is the json:
{
"setup": {
"game-info": {
"Rounds": 10,
"Players": 5
}
}
"list": "setup.Rounds.upfrom(1)",
}
I can already parse the first part of the json. So the CustomList setup field in the game class, already stores a map of { "game-info", { {"Rounds", 10}, {"Players", 5} } }. Each of these objects is also of type CustomList and they can be accessed through getElementAt().
But the json is parsed during runtime so I don't know what the names would be further down and what functions I would need to call. These are determined by "list" in the json. So how do I dynamically convert something of the format "setup.Rounds.upfrom(1)" into actual member accesses and calls?
So I have a class which is calling method from other class, but eventually it will return a string or so
This is my class: Person.cpp
Person::Person(){}
std::string Person::getName(void) {
return namespaceX::namespaceY::StringVal;
}
This is my mock / test class:
class MockPerson : public Person{
public:
typedef ::testing::StrictMock<Person> Strict;
MockPerson() : Person(){}
~MockPerson() override = default;
MOCK_METHOD0(getName, std::string ());
std::string callFunc(){
return Person::getName();
}
This is my test header file:
class PersonTest : public testing::Test {
public:
PersonTest () :
mock(std::make_shared<MockPerson ::Strict>()){}
~PersonTest (void) override = default;
std::shared_ptr<MockPerson ::Strict> mock;
};
This is my test:
#include "testHeader.hpp"
TEST_F(PersonTest , case1)
{
EXPECT_CALL(*mock, getName());
ASSERT_EQ(someString, mock->callFunc());
}
The test setup looks good to me however when I ran the test, it gives me:
Actual function call count doesn't match EXPECT_CALL(*mock, getName())...
Expected: to be called once
Actual: never called - unsatisfied and active
And the values return in the ASSERT statement is just the default value of the string ("").
Is there a way to go through it? I saw online that we should pass in an actual object to the function but in this case a very simple function causes more troubles than complex ones. Any help is appreciated.
First, compiling your example with g++ gives me the following error:
error: 'using element_type = class testing::StrictMock<Person>' {aka 'class testing::StrictMock<Person>'} has no member named 'gmock_getName'
This can be fixed by passing MockPerson as the template parameter for StrictMock, instead of passing Person:
typedef ::testing::StrictMock<MockPerson> Strict;
Second, your declaration of callFunc explicitly calls the getName function of the Person class. This bypasses the mocked version of getName and hence the instrumentation that Google Mock inserts to keep track of the number of function calls. Therefore, you get the assertion failure about the function call count mismatch. This can be fixed by making callFunc call the getName of the current class (MockPerson) instead:
std::string callFunc() { return getName(); }
Third, the mocked getName will return a default-constructed std::string, hence you get the "". You can change the behavior for all tests belonging to PersonTest, by adding this declaration in the PersonTest constructor:
ON_CALL(*mock, getName()).WillByDefault(Return("xyz"));
Or you can set the behavior for individual tests by modifying the EXPECT_CALL declarations to:
EXPECT_CALL(*mock, getName()).WillRepeatedly(Return("xyz"));
For both variants, the assert for your callFunc should then work as expected:
ASSERT_EQ("xyz", mock->callFunc());
I am coming from a javascript background, and in javascript if i had an array with elements [1,2,3] I can map through this array and perform a function on each iteration as so:
[1,2,3].map((i) => {
console.log(i);
return;
})
and i get
1
2
3
Trying same in dart
void main() {
[1, 2, 3].map((i) {
print(i);
return;
});
}
No output is printed, what am I missing?
JavaScript is different from Dart.
According to the documentation, the map method on an Iterable is meant to
return a new lazy Iterable with elements that are created by calling f on each element of this Iterable in iteration order.
In other words, the function in the map method isn't called until it is needed because it is lazily invoked. It will not return anything until something asks for what it is supposed to return. As long as the returned Iterable is not iterated over, the supplied function f will not be invoked.
Try in dartpad.dev
void main() {
var arr = [1, 2, 3];
var arr2 = arr.map((item)=> {
item * 2
});
print ('$arr2');
}
In the example above, the function in the map method of arr is called/invoked because it is requested for by $arr2 in the print function. Because of this, it runs the code inside it and the parameter in the print method gets printed out
Try
print([1, 2, 3].map((i) {
print(i);
return;
}));
You'll see that you get your desired result, because the function in the map method was invoked by the print method.
Since the method is lazy, it will not be invoked until it is requested. Adding a map method to an array doesn't invoke it. You've got to require what it returns for the function in the map method to be invoked.
I've got a method in UsersController
public function addMailbox($data)
{
$this->LoadModel('Mailbox');
$mailbox = $this->Mailbox->newEntity();
$mailbox->username = $data('username');
$mailbox->name = $data('name');
if ($this->Mailbox->save($mailbox)) {
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Error'));
}
, the code works fine when pasted into the add() method, but after using
$this->addMailbox($this->request->getData());
all i get is
error: Function name must be a string
Any ideas?
You've got the wrong syntax for accessing arrays in PHP, use square brackets:
$mailbox->username = $data['username'];
$mailbox->name = $data['name'];
The way you've got it, it's trying to call a function with the variable named in $data, but $data is an array not a string (see Variable functions for more info on that).
Also you shouldn't set user input on $mailbox properties directly - this bypasses validation. Instead just stick $data in newEntity():
public function addMailbox($data)
{
$this->loadModel('Mailbox'); // This also is not required if this function is inside the MailboxController
$mailbox = $this->Mailbox->newEntity($data);
if ($this->Mailbox->save($mailbox)) {
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Error'));
}
I need to create a generic method that splits a string and casts values
inline fun <reified T: Any> convertFromString(myString: String) : List<T>{
val castedList = ArrayList<T>()
for(item in myString.split(";")){
castedList.add(item as T)
}
return castedList
}
I call this method convertFromString<Int>("1;2;3;4;5;6") and expect to have output List<Int> but it fails during the cast item as T.
How can I cast all values to generic T?
I would rather suggest you to supply a transformation function, e.g.
inline fun <T: Any> convertFromString(myString: String, transformation: (String) -> T)
= myString.split(";")
.map(transformation)
.toList()
Note that you can't cast the String to anything else then String that is why item as T will not work. With the transformation function you ensure that it is transformed correctly (as long as you do not use item as T as the transformation ;-)).
Some sample usages/transformation functions could be:
val doubleList = convertFromString("123;123") { it.toDouble() }
val intList = convertFromString("123;123") { it.toInt() }
val objList = convertFromString("data=123;data=444") { yourParser.parse(it) }
Additionally with that approach you do not require the reified anymore. The inline however is still useful for any function containing a lambda function.