Returning a filtered range - d

I'm looking at filtering ranges, and getting a little confused. In D, I can write this code:
import std.stdio;
import std.range;
import std.algorithm;
auto filterNums(int[] vals)
{
int limit = 3;
return filter!(n => n >limit)(vals);
}
int main()
{
int[] nums = [1,2,3,4,5];
auto flt = filterNums(nums);
foreach(n;flt)
{
writeln(n);
}
return 0;
}
which gives the expected output of:
4
5
But this doesn't seem to be terribly safe code. If the filter is lazy evaluating, how does it know that limit is 3, once the local variable goes out of scope? Is my code just lucky that nothing else has over-ridden limit in memory? Also is the passed variable nums a reference, or a copied value: if a value, is the filter making its own copy?
Or perhaps I am not using filter in the correct way?

int is a value type, so the filter lambda receives a copy of it. If there were any scoping issues, the compiler would warn you.
int[] nums is a dynamic array managed by D's runtime. It consists of two parts: a value part, which contains its length and a pointer, which points to the dynamic part on the heap (where the ints are stored). The length and pointer itself are passed by value, which means appending or removing will not affect the original, but editing an element e.g. vals[1] = 1 would. To pass all of it by reference, you would use
filterNums(ref int[] vals).
Either way, the garbage collector keeps it around as long as it's needed, in this case it is stored in the filter construct.

Related

JsonCpp - modify an array of objects

I have a following array of objects in JsonCpp::Value:
[{"foo": "bar", "baz": ["Hello", "World"]},
{"Hello": "99bottles", "baz": ["bar", "foo"]},
{"beer": "hello", "world": ["foo"]}.... ]
I have to iterate over them and alternate them (remove some elements, add another one).
I can easily iterate over JsonArray with:
for (Json::Value::ArrayIndex i = 0; i != array.size(); i++) {
doc[i] = Json::Value();
Json::Value result = array.get(i, Json::Value());
std::cout<<"-------------------"<<std::endl;
std::cout<<result.toStyledString()<<std::endl;
}
But array.get() returns a copy of object. I won't be able to modify the object itself. I can create a new array and fill it with new objects based on values from the original one but it will be very costly.
Is it possible to achieve my goal with JsonCpp "in place"? And avoid additional memory overhead?
You are using get() which must return a value instead of a reference, because you can call with with an invalid i and it will return the default value you provide. I.e. for an array of size 2, you should be able to call array.get(17, Json::Value()) and you'll get back a default initialized Json::Value.
If you're certain the element exists, which is the case here, you can use array[i], which will give you a reference. Note that you need to change the type of result to Json::Value & as well, otherwise you'll still get a copy.
Note that this is all shown and explained in the API documentation for JsonCpp. I've never used this library myself, all the above info I got from that page.

Find End of Array Declared as Struct Type C++

I was recently learning to use struct datatype in c++. I know how the basics of struct datatype work and how to manipulate its variables. But I was wondering how would I determine the end of struct datatype array. For example consider the code below:
struct PersonDetails
{
string name, address;
int age, number;
}
Now in c++ program I create an array of struct type as follows:
PersonDetails Data[500];
Now consider that I have 30 records in data array and I have to display these records by looping through data array's index. So how would I determine that I have to loop through only first 30 indexes as the data is only stored in these indexes. As in char array we compare all indexes with '\0' to determine the end of array. Then what method will we use for Data[] array?
An edit that I have no idea about Vectors and the project i am working on requires me to use basics of c++(functions, control structures, loops, etc.).
It's not feasible.
For char[], back in times of C standardization, developers agreed to use \0 (integer value 0) as a special character marking end-of-string. Everything works as long as everyone is following this convention (i.e. both standard library functions and developers using those functions).
If you wanted to have such a convention for your type, you could just write down "Data object with both strings empty and both ints equal to 0 is array terminator", but you would have to follow this convention. You'd have to write functions that would stop processing array upon finding such an object. You'd have to make sure that in every array there is at least one such object.
Instead
You should use std::vector<Data> which can automatically accomodate for any number of Data objects and will now precisely how many of them are currently stored (using size() method)
or
use std::array<Data, 30>, which can store exactly 30 objects and you can assume all of them are valid objects.
IMHO the correct way to solve this is to not use a C-style array, but instead use a std::array or std::vector that knows it's .size().
Iterating a std::vector or std::array is trivial:
for (const auto& element : Data_array) {
// Do something with the array element
}
See also:
https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/language/for
https://en.cppreference.com/w/cpp/language/range-for
The simplest solution is to just have a separate variable specifying how many array elements are filled in.
PersonDetails Data[500];
int numPersons = 0;
Data[0].name = ... ;
Data[0].address = ...;
Data[0].age = ...;
Data[0].number = ...;
numPersons = 1;
Data[1].name = ... ;
Data[1].address = ...;
Data[1].age = ...;
Data[1].number = ...;
numPersons = 2;
...
Then you use that variable when looping through the array.
for (int i = 0; i < numPersons; ++i)
{
// use Data[i] as needed...
}
I don't really agree using std::array makes any difference.
The problem you currently have doesn't occur in whether we have such an element in the container, but whether the element we are inspecting useful.
Consider the example you gave, for an array of chars, we simply check whether one of the elements is \0 to decide whether or not we should halt the iteration.
How does that work? The ramaining elements, of course, default initialized to be \0, they exist, but of no use.
Similarly, you can check, in this example, whether
name.empty()
Or, in order to avoid any possible exception, as mentioned in the comment section, do this:
add user-defined constructor to the class ( or struct, they are same actually.) which initialize age to -1 and then check if age == -1.
because it's impossible for a people not having any name, that means, you have not assign to any of the remaining elements. Thus, stop iteration.
As a supplement, using std::vector makes sense, but if that isn't a option for you for the time being, you don't need to consider it.

Why function's return statement is not usual int[ ]

I have just started to use Dlang and it seems to be ideal for people who want a safer C language. In addition it has modern paradigms also like functional programming.
I am trying following code to convert a list of numbers as strings to list of integers:
import std.stdio;
import std.array;
import std.conv;
int[] list_str2int(char[][] slist){ // this function should convert a list of numbers as char[] to integers
int[100] intcol;
int N = cast(int)slist.length;
foreach(int i; 0..N){
char[] temp = slist[i];
temp = split(temp, ".")[0]; // effectively this is floor; to!int does not work if '.' is there;
intcol[i] = to!int(temp); // not working;
}
return intcol; // error from this statement;
}
void main(){
char[][] strlist = cast(char[][])["1.1","2.1","3.2","4.4"];
int[] newintlist = list_str2int(strlist);
writeln("Converted list: ", newintlist);
}
But getting following error:
testing.d(13): Error: returning cast(int[])intcol escapes a reference to local variable intcol
Failed: ["/usr/bin/dmd", "-v", "-o-", "testing.d", "-I."]
I cannot understand why there is error on return line of the first function where the variable is int[].
Where is the problem and how can it be solved? Thanks for your help.
int[100] is a static array (a value type), and is located on list_str2int's stack frame - therefore it will cease to exist once the function returns. The function's return value, int[], is a slice (a reference type), which does not hold any data, but refers to a contiguous number of integers somewhere in memory. The statement return intcol; thus takes a slice of the static array, however, returning it is invalid because the slice would point to memory that would no longer be valid after the function returns.
You have a few options:
Declare the return type as int[100] also. Making it a value type, the integers will be copied to the caller's stack frame.
Allocate the array in the program's heap by declaring and initializing the array as auto intcol = new int[100];. This will make intcol a slice of memory in the heap. Memory in the heap is owned by the garbage collector, and has effectively infinite lifetime.
An option that's further from the above but more idiomatic to modern D is to use ranges. Your program could be rewritten to a single statement as follows:
import std.algorithm.iteration;
import std.stdio;
import std.array;
import std.conv;
void main()
{
["1.1", "2.1", "3.2", "4.4"]
.map!(item => item
.split(".")[0]
.to!int
)
.array // optional, writeln and co can write ranges
.writefln!"Converted list: %s";
}
int[] is a slice, it can use dynamic allocation.
The int[100] is an array of 100 elements. It is allocated on the stack
Just like in C, you can't return local memory from a function, you can't return intcol, as the memory behind it becomes invalid after the function returns.
It seems unknown to me, if you want to use dynamic arrays or static. If you want to use dynamic arrays, then stick to them.
import std.stdio;
import std.array;
import std.conv;
int[] list_str2int(char[][] slist){ // this function should convert a list of numbers as char[] to integers
int N = cast(int)slist.length;
int[] intcol = new int[N];
foreach(int i; 0..N){
char[] temp = slist[i];
temp = split(temp, ".")[0]; // effectively this is floor; to!int does not work if '.' is there;
intcol[i] = to!int(temp); // not working;
}
return intcol; // error from this statement;
}
void main(){
char[][] strlist = cast(char[][])["1.1","2.1","3.2","4.4"];
int[] newintlist = list_str2int(strlist);
writeln("Converted list: ", newintlist);
}
will output:
Converted list: [1, 2, 3, 4]

Select a random object from an array of objects

I'd like to implement a function that selects a random object from an array of objects and returns it to me. It should be something like (in C++ instead of psuedocode):
getRandomObject(objectList) {
return objectList[int(random(length of objectList))];
}
My current code looks like this, but doesn't seem to work:
//definition of random selector
object getRandomObject(Object* objectList) {
return objectList[int(ofRandom(0, sizeof(objectList)))];
};
//create a pointer for the listOfObjects
object* listOfObjects;
//create an empty object to put the randomly selected object in
object randomObject;
//later in the code, populate the array:
object* listOfObjects[] = {
new Object(),
new Object(),
new Object()
};
//select random object
randomObject = getRandomObject(listOfObjects);
But this seems to return a segmentation fault. A few problems I've noticed:
sizeof() returns the size of the pointer in getRandomObject, not the size of the array. is there a good way to get the size of the array? It might involves not using a float* pointer for the array. Is this a good use case for vectors?
I think that much of the problem lies in how I'm creating my arrays, and not so much in how I'm selecting the random object from them. I'm relatively new to C++ (coming from a Java background), so much of pointers / references / memory management in general is new to me.
thanks!
I see one definite problem and one possible one. The definite problem is that sizeof(objectList) returns the size of the objectList pointer, which will be 4 or 8 on most platforms. It does not return the number of elements in the array, objectList. Either pass in the length of the array or use std::vector or std::array.
The second possible problem relates to ofRandom. Make sure that ofRandom(a,b) returns numbers >= a, but strictly < b. If it returns values <= b, then you'll need to us ofRandom(0, objectVector.size() - 1). Typically, functions like this are written to return values strictly < b, but you should check.
C++ has an array template class that you may want to consider using. Check out the documentation here:
http://www.cplusplus.com/reference/array/array/
This type has a method, size(), that will return the length of the array.
When the sizeof operator is applied to an array, it yields the total
number of bytes in that array, not the size of the pointer represented
by the array identifier.
Quote
So you take the space alocated for your whole array and divide by the memory need just for one element: sizeof(objectList) / sizeof(*objectList).
Mr Fooz noticed issues that cause a segfault.
Other compilation issues are:
listOfObjects is declared with 2 different types: object* and object*[3] while getRandomObject expects a type Object*.
listOfObjects[] contains elements of type object* while getRandomObject reads elements of type Object and returns object.

Returning multiple data items from a function in C or C++

I am confused on a couple homework questions I have...
Can you return multiple data items from a function by using return()? Can a function only return one value, unless it is a pointer to an array?
I believe that the answer is that a function can return multiple data items by returning a structure. Then, returning a pointer to an array is not the only way - if that is a way?
But there seems to be a lot of discussion on this topic and so I want to make sure I have at least the basic idea correct: You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
With C++0x/C++11 you can use this:
#include <string>
#include <iostream>
#include <tuple>
using namespace std;
tuple<int, unsigned, string, int> getValues()
{
return tuple<int, unsigned, string, int>(1, 2, "3", 4);
}
int main()
{
int a;
unsigned b;
string c;
int d;
tie(a, b, c, d) = getValues();
cout << a << ", " << b << ", " << c << ", " << d << endl;
return 0;
}
Compile it with
g++ tuple_test.cpp -std=c++0x -o tuple_test
And and if you run the programm it will output this:
1, 2, 3, 4
But it's better to use references like this (i would say):
void getValues(int& a, unsigned& b, string& c, int& d)
{
a = 1;
b = 2;
c = "3";
d = 4;
}
int main()
{
...
getValues(a, b, c, d)
...
}
Uch thats what I get for not reading the question carefully...
Can a function only return one value, unless it is a pointer to an array?
Yeah you only can return 1 single value, but this single value can include multiply values (struct, class, array).
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
True. But when you use pointers it depends on how you use it.
When you dynamic allocate it each function call it wont be very efficient and you would need to deallocate the memory manually after usage. When you use a global-array/struct it will be efficient. But can give you problems when you call the function multiply times.
In addition to what is already said in this thread, in C++11 you can return structures initialized using uniform initialization:
struct XYZ {
int x;
int y;
int z;
};
XYZ foo() {
return {1, 2, 3};
}
Personally I prefer returning structures with named members rather than tuples because the latter doesn't provide names for its members.
That is correct.
You can however "return" multiple items, by adding parameters that are passed by reference, then writing the multiple results to them.
A function can indeed only return one 'thing' with its return statement. That thing can, however, be a pointer (C & C++ arrays are simply pointers in disguise), a reference (a pointer which can't be reseated or array-indexed) or an object, which may encapsulate multiple things.
If you return a structure, you're passing back the entire structure. If you return a pointer or reference, you are returning only the address of the structure - so you had better not return a reference or pointer to a structure that goes out of scope when the function returns! Doing so invokes undefined behavior, which most likely (but not always) is a segmentation fault.
If you want a bigger picture about this read about passing parameters by value and passing by reference it also applies for returning parameters.
As you mentioned:
You can return multiple data items using a structure but using pointer (I don't understand this) will use memory more efficiently. Is this correct?
Lets say you have some structure:
struct BigStructure{
int array[1000];
double otherData[1000];
//... etc
};
and some method:
BigStructure workWhenCopying(BigStructure bigStruct){
// some work with a structure
return bigStruct;
}
This method illustrates the case when you pass parameters to the method and return it by value, which means that each time you call this method you are copying the method's argument into another place in memory. This copying takes time and when you have bigger structures it slows down your program run time thus it is more efficient to pass big structures by reference.
void workWithReference(BigStructure & bigStruct){
// do some work
}
In this case you are not copying whole data structure, just passing the address of the memory where this structure resides. You also don't need a return statement since changes to that structure object will be visible outside this method. But if you will reassign bigStruct to a new memory location it will be visible only within local method: workWithReference
I hope it's more clearer now;)