In Rascal, say I have the code:
value x = 2;
data Exp = con(int n);
Is there a way to call con(x), while x is a value (but actually an integer), without knowing on beforehand what the type of con's first argument is supposed to be (thus without explicitly casting it to an int)?
Why is it possible to call a function, say int something(int n) = n, with an integer defined as a value (e.g. value y = 2) passed into its first argument, while it gives me an error when I try to do the same with user-defined ADTs?
When you call a function in Rascal it actually is doing a pattern match on the arguments. So, if you define int something(int n) = n;, and then call something(x), it matches x with int n, sees that x is actually an int (so it can bind the value to n), and calls the function.
If you were to define value x = 2.5 instead and then call something(x) you would get an error since it cannot bind the value 2.5 to int n. You could overload something with a second definition that takes a real instead, like int something(real r) = toInt(r);, and it would then work. Two items to note here, though: something needs to return the same type in both cases, and you need to import util::Math to get access to toInt.
When you are using a constructor, like con(x), it doesn't do a pattern match for you automatically. The type that you give it has to match the type it expects. If you know that x will always be an int, it would be best to just declare it as such. Another option would be to create a function like Exp makeCon(int n) = con(n); which you could then use as you would like, i.e., Exp myExp = makeCon(x);. It would be best in this case to include a default version of the function, just in case you give it something unexpected, like default Exp makeCon(value x) { throw "Unexpected value <x>"; }, this way if you ever try to create a con with something that isn't an int you will get an error that you can handle, with the ability to create your own error message, add additional error handling versus just showing a message, see the value causing the problem, etc, versus just having the interpreter give an error (which may not give you all the info you want).
Related
I'm trying to learn C++ at my own pace via an online course. There is a function declaration and also there is an integer declaration just after that, which is q.
I don't understand what purpose the "q" serves in the code.
I tried to print out each step and it didn't make sense. I literally don't see the point of having a "q" in the foo function or what it does.
#include<stdio.h>
int foo (int q) {
int x = 1;
return (q + x);
}
int main (){
int x = 0;
while (x < 3) {
printf ("%i\n", x);
x = x + foo(x);
}
}
This code gives me
0
1
Seems like the "q" is incrementing x but I don't see the reason why because we didn't assign it to anything but just saying (int q)
In the code you posted, q is an argument to the function foo and foo will return the value of its argument (q) +1.
It is a call by value function call where foo() get call by passing the value to q variable.
If you not declare any argument in the function it will give an error because it's int q only to get the value from the main function.
So here when first time foo get call - it's return 1 and after that it's return 2 .
So in second time x=1+2=3
3>3 condition false.
It print only 0,1.
q is a parameter. That is, it is something in a function that accepts a value from the caller. As w3schools puts it:
Information can be passed to functions as a parameter. Parameters act as variables inside the function.
Parameters are specified after the function name, inside the parentheses. You can add as many parameters as you want, just separate them with a comma:
Probably couldn't have explained it better myself.
This code gives me 0 1 Seems like the "q" is incrementing x but I don't see the reason why because we didn't assign it to anything but just saying (int q)
Ah, so, we actually did assign it to something. It might just not be noticeable. We did it when we called foo:
x = x + foo(x);
Here, by putting x between the parenthesis, we set q to the value of x (which appears to be 0, in this case). That means, q will have the value of x (0) inside the function call.
We also could have set it to something else, like 3:
x = x + foo(3);
Here, q is set to 3, because 3 is inside the parenthesis.
int foo (int q)
declares a function that takes an input parameter, q. The value q takes, in foo, depends on the value that is passed to it. In this case, when you call it with:
foo(x)
You state: run the code in foo, but give to q, upon entering the function, the value of x in main(). When you start programming, at first, this is misleading as q and x appear to be different variable. You'll get used to it.
You must also realise that the x in foo has nothing to do with the x in main. Those are different variables.
Thank you for all your answers and comments.
It seems like the q is the argument passed in and x is just there for representing an integer (redundantly).
It'd have been better if the code just used the integer 1 as:
int foo (int q) {
return (q + 1);
In a question, the first prototype given below is called valid
int Function(int Tmp = Show());
while in the second case it is called as invalid declaration.Why?
float Function(int Tmp = Show(int, float));
here is the link to the question- http://www.indiabix.com/cpp-programming/functions/discussion-61
The fact that Show is being used to establish a default argument value is a red herring.
Show(int, float) doesn't make sense in the context of calling that function Show, whereas Show() does.
When you call a function in C++, you supply parameter values, not the types.
Because you don't pass any actual parameters to the Show() function in the second case. You would want something like
float Function(int Tmp = Show( 1, 2.3 ));
The first case doesn't need parameters because it is presumably a call to a function that looks like this:
int Show();
Lets say I have a function
void doStuff(vector<int> &a, int b, vector<int> &c> {
c = vector<int>(a.size());
for (int i = 0; i < a.size(); i++) {
c[i] = a[i] + b;
}
}
obviously, upon seeing the function, we know that "c" is the output.
For anybody who hasn't seen the function definition though, it remains a mystery unless i name c something like "output_c". Maybe I'm just being vein but I don't like naming things "ouput_xxx", is there any syntax candy for letting the user of the function know that its supposed to be the output?
Syntax, by itself, can be a guide to indicate which one is an input argument and which one is an output argument. However, an output argument can also serve as an input argument too. You cannot tell that by just looking at the signature.
Examples:
int foo(int arg); // The argument is copy by value. It can only be an input argument.
void foo(std::vector<int> const& arg); // The argument is by const&.
// It can only be an input argument.
void foo(std::vector<int>& arg); // The argument is by &. It can be:
// 1) an output argument.
// 2) an input and output argument.
// 3) an input argument (bad practice)
You could add a preprocessor directive:
#define OUT
and put it in the parameter list like so:
void doStuff(vector<int> &a, int b, OUT vector<int> &c) ...
I think I've seen some APIs do something like this. That way it is explicitly stated in the function signature but you don't have to modify the variable names. The code is also unchanged at compile time since OUT is not defined to be anything, it is just a defined symbol.
I think, though, I would rely on your own documentation when writing the function and/or return-by-value instead of doing something like this. You could also make use of the const keyword to flag a parameter that is guaranteed not to change - that's what the syntax is designed for.
EDIT: thanks for all the speedy responses, I have a much better understanding of this concept now. Also, I'll try to make my error messages more clear next time.
EDIT: updated with my newest code. the error happens on line 18. Also, I'm beginning to wonder if my latest issue has to do with the original class itself?
I'm trying to teach myself classes and objects in C++. I did it once by just declaring a void function, outputting something on the screen, calling the object in main and everything worked fine.
Now, I wanted to expand upon this and make a simple addition thing. However, I get a couple errors on Code Blocks:
error: invalid use of non-static member function 'int Addition::add(int, int)'
error: no matching function for call to 'Addition::add()'
Here's my code:
#include <iostream>
using namespace std;
class Addition {
public:
int add (int x, int y) {
int sum;
sum=x+y;
return sum;
}
};
int main()
{
int num1;
int num2;
int ans=addobj.add(num1,num2);
Addition addobj;
addobj.add(num1,num2);
cout<<"Enter the first number you want to add"<<endl;
cin>>num1;
cout<<"Enter the second number you want to add"<<endl;
cin>>num2;
cout<<"The sum is "<<ans<<endl;
}
One of the most important things, a developer should learn to do is to read compiler's messages. It's clear enough:
error: no matching function for call to 'Addition::add()'
Your function in your class is
int add (int x, int y)
it takes 2 arguments and you pass none:
addobj.add();
You have 2 options:
create and initialize x and y inside your main and pass them as arguments
make add without parameters, create x and y inside add's body, as their values are taken from user input.
In this case, as the function's name is add, I'd chose the first option:
declare int x, y; inside your main
read the user input inside the main (the part, where you use cin and cout)
pass the x and y as arguments to add like this: addobj.add( x, y );
store the result (if needed), like this: int result = addobj.add( x, y );
You declared a method add(int, int) that takes two integers as arguments; you have to supply those arguments when you call it. It would be nice to print the returned value, as well:
Addition addobj;
std::cout << addobj.add(1, 2) << std::endl;
Your add function takes two arguments, yet you call it with none, so no matching function could be found. You must call the function as it was declared, i.e.,
addobj.add(1, 2);
Your function takes two arguments and yet you call it without providing them. You need to provide the two integer arguments that your function requires. To be useful you should store the result too. Something like this
int a = 1;
int b = 2;
int result = addjobs.add(a,b);
int add (int x, int y=1)
int main ()
{
int result1 = add(5);
int result2 = add(5, 3);
result 0;
}
VS
int add (int x, int y)
int main ()
{
int result1 = add(5, 1);
int result2 = add(5, 3);
result 0;
}
What is the advantage of using the default function parameter, in term of execution speed, memory usage and etc? For beginner like me, I sometimes got confused before I realized this usage of default function parameter; isn't it coding without default function parameter made the codes easier to read?
Your add function is not a good example of how to use defaulted parameters, and you are correct that with one it is harder to read.
However, this not true for all functions. Consider std::vector::resize, which looks something like:
template<class T>
struct vector_imitation {
void resize(int new_size, T new_values=T());
};
Here, resizing without providing a value uses T(). This is a very common case, and I believe almost everyone finds the one-parameter call of resize easy enough to understand:
vector_imitation<int> v; // [] (v is empty)
v.resize(3); // [0, 0, 0] (since int() == 0)
v.resize(5, 42); // [0, 0, 0, 42, 42]
The new_value parameter is constructed even if it is never needed: when resizing to a smaller size. Thus for some functions, overloads are better than defaulted parameters. (I would include vector::resize in this category.) For example, std::getline works this way, though it has no other choice as the "default" value for the third parameter is computed from the first parameter. Something like:
template<class Stream, class String, class Delim>
Stream& getline_imitation(Stream &in, String &out, Delim delim);
template<class Stream, class String>
Stream& getline_imitation(Stream &in, String &out) {
return getline_imitation(in, out, in.widen('\n'));
}
Defaulted parameters would be more useful if you could supply named parameters to functions, but C++ doesn't make this easy. If you have encountered defaulted parameters in other languages, you'll need to keep this C++ limitation in mind. For example, imagine a function:
void f(int a=1, int b=2);
You can only use the given default value for a parameter if you also use given defaults for all later parameters, instead of being able to call, for example:
f(b=42) // hypothetical equivalent to f(a=1, b=42), but not valid C++
If there is a default value that will provide correct behavior a large amount of the time then it saves you writing code that constantly passes in the same value. It just makes things more simple than writing foo(SOME_DEFAULT) all over the place.
It has a wide variety of uses. I usually use them in class constructors:
class Container
{
// ...
public:
Container(const unsigned int InitialSize = 0)
{
// ...
}
};
This lets the user of the class do both this:
Container MyContainer; // For clarity.
And this:
Container MyContainer(10); // For functionality.
Like everything else it depends.
You can use it to make the code clearer.
void doSomething(int timeout=10)
{
// do some task with a timeout, if not specified use a reasonable default
}
Is better than having lots of magic values doSomething(10) throughout your code
But be careful using it where you should really do function overloading.
int add(int a)
{
return a+1;
}
int add(int a,int b)
{
return a+b;
}
As Ed Swangren mentioned, some functions have such parameters that tend to have the same value in most calls. In these cases this value can be specified as default value. It also helps you see the "suggested" value for this parameter.
Other case when it's useful is refractoring, when you add some functionality and a parameter for it to a function, and don't want to break the old code. For example, strlen(const char* s) computes the distance to the first \0 character in a string. You could need to look for another characted, so that you'll write a more generic version: strlen(const char* s, char c='\0'). This will reuse the code of your old strlen without breaking compatibility with old code.
The main problem of default values is that when you review or use code written by others, you may not notice this hidden parameter, so you won't know that the function is more powerful than you can see from the code.
Also, google's coding style suggests avoiding them.
A default parameter is a function parameter that has a default value provided to it. If the user does not supply a value for this parameter, the default value will be
used. If the user does supply a value for the default parameter, the user-supplied value is used.
In computer programming, a default argument is an argument to a function that a programmer is not required to specify. In most programming languages, functions may take one or more arguments. Usually, each argument must be specified in full (this is the case in the C programming language)
Advantages of using default parameter, as others have pointed out, is indeed the "clarity" it brings in the code with respect to say function overloading.
But, it is important to keep in mind the major disadvantage of using this compile-time feature of the language: the binary compatibility and default function parameter does not go hand in hand.
For this reason, it is always good to avoid using default params in your API/interfaces classes. Because, each time you change the default param to something else, your clients will need to be recompiled as well as relinked.
Symbian has some very good C++ design patterns to avoid such BC.
Default parameters are better to be avoided.
let's consider the below example
int DoThis(int a, int b = 5, int c = 6) {}
Now lets say you are using this in multiple places
Place 1: DoThis(1);
Place 2: DoThis(1,2);
Place 3: DoThis(1,2,3);
Now you wanted to add 1 more parameter to the function and it is a mandatory field (extended feature for that function).
int DoThis(int a, int x, int b =5, int c=6)
Your compiler throws error for only "Place 1". You fix that. What about other others?
Imagine what happens in a large project? It would become a nightmare to identify it's usages and updating it rightly.
Always overload:
int DoThis(int a) {}
int DoThis(int a, int b {}
int DoThis(int a, int b, int c) {}
int DoThis(int a, int b, int c, int x) {}