Pass-by-name and Pass-by-value-result - parameter-passing

For my programming languages class, I am trying to understand how pass-by-name and pass-by-value-result work. I realize these aren't used hardly at all in mainstream languages, but I am wanting to get a feel for how they work. As an example (language agnostic):
void swap(int a, int b){
int t;
t = a;
a = b;
b = t;
}
void main() {
int val = 1, list[5] = {1, 2, 3, 4, 5}
swap(val, list[val]);
}
What would the values of val and list be after swap is called for both pass-by-value-result and pass-by-name.
An explanation would be great too.
From what I deduced, it got value-result: val=2, list={1,1,3,4,5} and name: val=3, list={1,2,1,4,5}. I'm very unsure about those results.
Also does it change the way both of these methods work when an array is passed as opposed to a single int? Thanks for any help in advance.

this code explain one of the problem of pass by name
this is why
in swap this is what happen
void swap(int a, int b){
int t;
t = a; //t=val; t=1
a = b;// val=list[val]; val=list[1]=2
b = t;// list[val]=t; list[2]=1
}
void main() {
int val = 1, list[5] = {1, 2, 3, 4, 5}
swap(val, list[val]);
}
as you can see the val changed at val=list[val] and it isn't the same val you passed anymore
as for pass by value result
void swap(int a=1, int b=2){
int t;
t = a; //a=1 so t=1
a = b; //b=2 so a=2
b = t; //b=1 so it and it return the right parameter so list[1]=2
}
i hope this helped

If you mean pass by name as pass by reference then the result will be the same as by value.
This is because you are only switching references between val and list position val. You are not passing an array reference.
Think of a var as a pointer to a block of memory that contains a value.

Related

What does Dart "Error: Can't return a value from a void function." mean?

I can't understand what void function in Dart means. Below is an example where output from map method can't be returned. I'm new to Dart and would appreciate simplified explanation.
void main() {
var myList = [1, 2, 3];
var output = myList.map((i) => i * 2);
return output;
}
void A special type that indicates a value that’s never used. Functions like printInteger() and main() that don’t explicitly return a value have the void return type. For more information, see this article.
https://dart.dev/guides/language/language-tour#a-basic-dart-program
In short, it is a type you use to indicate that your method does not return any (usable) value. For main method, you cannot return any value. You can instead e.g. print the result using print like:
void main() {
var myList = [1, 2, 3];
var output = myList.map((i) => i * 2);
print(output); // (2, 4, 6)
}

How to set data pointed to by argument using Critcl?

I would like to express something like this in Critcl:
void setter(int* grid, int value, int x, int y) {
grid[xy2addr(x,y)] = value;
}
I'm in particular stuck on how to deal with int* grid in Critcl. object? bytes? Custom type maybe?
Related to this question.
This case doesn't map very well onto Tcl's value model. The issue is that grid is (a pointer to) an updateable value collection. There are two ways of modelling this in Tcl in general:
As an opaque object.
As a variable containing a Tcl list (since in model terms, while Tcl values are thought of as immutable, Tcl variables are mutable).
I'll describe how to do both below, but I'm guessing that you're going to be thinking of these zOrder things as a distinct mutable type and that the additional modest one-time overhead of making the custom type will suit you far better.
Opaque (Mutable) Objects
When working with opaque objects, you pass handles to them (basically just a name) around and then you unpack them as a custom Critcl type. The trick is to create some helper functions in C to do the mapping (this can be in a critcl::ccode command) that does the mapping between names and pointers. This is slightly messy to do, but is just about building a couple of hash tables.
critcl::ccode {
static Tcl_HashTable *zOrderMap = NULL, *zOrderRevMap = NULL;
static Tcl_Obj *
MakeZOrderObj(int *zOrder) {
/* Initialize the two maps, if needed */
if (zOrderMap == NULL) {
zOrderMap = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitObjHashTable(zOrderMap);
zOrderRevMap = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(zOrderRevMap, TCL_ONE_WORD_KEYS);
}
int isNew;
Tcl_HashEntry *hPtr = Tcl_FindHashEntry(zOrderRevMap, (char*) zOrder, &isNew);
if (!isNew) {
return Tcl_GetHashValue(hPtr);
}
/* make a handle! */
Tcl_Obj *handle = Tcl_ObjPrintf("zOrder%ld", (long) zOrder);
Tcl_SetHashValue(hPtr, handle);
Tcl_IncrRefCount(handle);
hPtr = Tcl_CreateHashEntry(zOrderMap, (char*) handle, &isNew);
Tcl_SetHashValue(hPtr, zOrder);
return handle;
}
static int
GetZOrderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int **zOrderPtr) {
Tcl_HashTable *hPtr;
if (!zOrderMap || (hPtr = Tcl_FindHashEntry(zOrderMap, (char *) objPtr)) == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("no such zOrder \"%s\"",
Tcl_GetString(objPtr)));
return TCL_ERROR;
}
*zOrderPtr = (int *) Tcl_GetHashValue(hPtr);
return TCL_OK;
}
}
With that helper code in place, you can then define a custom Critcl type like this:
critcl::argtype zOrder {
if (GetZOrderFromObj(interp, ##, #A) != TCL_OK) {
return TCL_ERROR;
}
} int*
critcl::resulttype zOrder {
if (rv == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, MakeZOrderObj(rv));
return TCL_OK;
} int*
That then lets you write your real code as something like this. Note that grid is defined as being of (custom) type zOrder, and that those can only be manufactured by some code that returns a zOrder as its result.
critcl::cproc setter {zOrder grid int value int x int y} void {
grid[xy2addr(x,y)] = value;
}
(The deletion function that removes the entries from the hash tables and deletes the C array is left as an exercise.)
Tcl List Variable
The other way of doing this is to make zOrder values be held in Tcl variables as lists of integers. This can be nice because it lets you look inside easily, but it can also be not so nice in other ways, as the code is not constrained to work with proper values and you expose your cprocs to more details of what's happening in Tcl.
critcl::cproc setter {Tcl_Interp* interp object varName int value int x int y} ok {
/* Unpack the list of ints from the variable */
Tcl_Obj *listObj = Tcl_ObjGetVar2(interp, varName, NULL, TCL_LEAVE_ERR_MSG);
if (listObj == NULL)
return TCL_ERROR;
Tcl_Obj **listv; int listc;
if (Tcl_ListObjGetElements(interp, listObj, &listc, &listv) != TCL_OK)
return TCL_ERROR;
int *grid = alloca(sizeof(int) * listc);
for (int i=0; i<listc; i++)
if (Tcl_GetIntFromObj(interp, listv[i], &grid[i]) != TCL_OK)
return TCL_ERROR;
/* The core of the functionality */
grid[xy2addr(x,y)] = value;
/* Repack the list of ints from the variable; this code could be optimized in this case! */
for (int i=0; i<listc; i++)
listv[i] = Tcl_NewIntObj(grid[i]);
listObj = Tcl_NewListObj(listc, listv);
Tcl_ObjSetVar2(interp, varName, NULL, listObj, 0);
return TCL_OK;
}

Reference to class method

I would like to pass to a function a reference to a class method.
For example:
#include <functional>
struct Foo
{
int f(const int& val) const
{
return val+2;
}
};
int caller(const std::function<int(const int&)>& f)
{
return f(1);
}
int main()
{
caller([](const int& val){return val+2;}); // OK
Foo foo;
caller(foo.f); // WRONG
return 0;
}
How can I fix the second call of caller() (NB: Foo:f() is not static)?
In your case, function f doesn't use any member of Foo so it can be declared static
static int f(const int& val)
and passed as:
caller(&Foo::f);
But suppose that f cannot be declared static and you want to pass "reference" to member function of particular object.
You can use lambda in that case:
Foo foo;
caller(
[&foo](const int& val){
return foo.f(val);
}
);
foo object is captured in square brackets (in this case by reference) so that you can call f member function on that particular object.
Although it is not part of your question, I should add that it is not really useful to pass int by const reference, as you will not gain any performance improvement that way. Actually, your code will run slower than if you pass int by value.

In C++, how to use find_if on a map with a functor when keys are struct with strings?

I have a stl::map which key type is a custom struct. I want to know if this map already has a key with a specific string as component (noted as "id" below), whatever the value of its other components. Inspired by this answer and this one also, I try to use stl::find_if with a custom functor:
map<myStruct, vector<size_t> > myMap;
struct myStruct
{
string a, b, c, id;
};
struct checkId : unary_function<pair<myStruct, vector<size_t> >, bool>
{
private:
string _exp;
public:
checkId (myStruct x) : _exp(x.id) {}
bool operator() (const pair<myStruct, vector<size_t> > & p) const
{
return p.first.id.compare(_exp) == 0;
}
};
map<myStruct, vector<size_t> >::iterator it;
myStruct newS; // to be initialized, but not shown here
it_mP2P = find_if(myMap.begin(), myMap.end(), checkId(newS));
When I compile this, gcc returns me:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = myStruct]’:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:347: instantiated from ‘_Tp& std::map<_Key,_Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = myStruct, _Tp = std::vector<long unsigned int, std::allocator<long unsigned int> >, _Compare = std::less<myStruct>, _Alloc = std::allocator<std::pair<const myStruct, std::vector<long unsigned int, std::allocator<long unsigned int> > > >]’
myprogram.cpp:386: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’
Does this mean that I have to overload the operator "<" to work with my custom struct if I want to use my functor "checkId"? How can I do this? I am not a C++ expert,so thanks in advance for any piece of code.
http://codepad.org/VYNqdZeF
struct myStruct
{
std::string a, b, c, id;
bool operator<(const myStruct& rhs) const //HERES THE MAGIC
{return id < rhs.id;} //WHEEEEEEEEEEEE!
};
This is required to make std::map<myStruct, stuff> work, without passing a custom comparison functor.
It's got nothing to do with checkId. The following demonstrates the same problem:
map<myStruct, vector<size_t> > myMap;
struct myStruct
{
string a, b, c, id;
};
std::map is a sorted map (it's usually implemented as a binary search tree)... the key type (myStruct in this case) must have operator< implemented simply to construct the map.
If you don't need fast lookups, you can just use a vector< pair< myStruct, vector<size_t> > >; if you need fast lookups, you have to add some kind of structure to myStruct. For a std::map this must be a comparison operator; alternatively you can use a std::unordered_map (in C++11; this is usually implemented as a hash table) -- in this case you will need to implement a hash function.
See the documentation of std::map and std::unordered_map for more details.
This has nothing to do with your use of find_if.
For a type to be a key of a map, it needs to be comparable, either by implementing operator< or by providing a comparator as a template parameter of the map.
Mooing Duck's answer is the easiest to do, but not the most flexible
if you go and write
struct myStruct
{
std::string a, b, c, id;
bool operator<(const myStruct& rhs) const
{return id < rhs.id;}
};
then all your maps that have myStruct as a key, will have to be sorted
by id.
Suppose you have one map that needs to be compared by a, and another one by b. If you put operator<() inside your myStruct, then you will have coupled the struct with its users, tightly, which is not good programming practice.
Instead, you could set a compare function to each map:
struct myStruct
{
std::string a, b, c, id; // keep your struct unchanged, and independent of clients
};
bool Compare_by_a(const myStruct &s1, const myStruct& s2) {
return s1.a < s2.a;
}
bool Compare_by_b(const myStruct &s1, const myStruct& s2) {
return s1.b < s2.b;
}
bool Compare_by_id(const myStruct &s1, const myStruct& s2) {
return s1.id < s2.id;
}
map<myStruct, vector<size_t>, Compare_by_a > map1;
map<myStruct, vector<size_t>, Compare_by_b > map2;
map<myStruct, vector<size_t>, Compare_by_id > map3;

how to use stl map for more than one fields without nesting another map in it

i have to use stl map containing 3 values : float(key) , int ,int.
For the last two ints without using another map , how can i declare my map and insert values in it?
Thanks in advance.
struct foo
{
int x;
int y;
};
...
std::map<float,foo> myMap;
...
foo a = { 5, 2 };
myMap[3.2] = a;