Is it possible to annotate Dafny method parameters as mutable, without them being objects?
My goal is to be able to verify
method testMethod(a:int, b:int) returns (res :int) {
res :=0;
a := (a - b);
assert a < (a-b);
}
Ignoring the fact this is obviously an absurd assertion, Dafny complains about the LHS not being a mutable variable, while I'd like to avoid introducing temporary variables.
All in-parameters in Dafny are immutable (including in-parameters of reference types, though with an appropriate modifies clause a method can make modifications in the heap by dereferencing such a parameter). So, you need to use a local variable to store the expression a - b in your example. For example:
method testMethod(a:int, b:int) returns (res:int) {
res := 0;
var myLocalA := a - b;
assert myLocalA < myLocalA - b;
}
If you are bothered by having to introduce a new name for the local variable, Dafny actually allows you to give a local variable the same name as an in-parameter. If you find that to be in your style, you can write:
method testMethod(a:int, b:int) returns (res:int) {
res := 0;
var a := a - b;
assert a < a - b;
}
Note that the right-hand side of the assignment to the local variable a mentions the in-parameter a (because the local variable a is not quite yet in scope at that time).
If you do this a lot, you can also start your method off with a statement
var a := a;
This looks ridiculous and may be confusing until you realize what's going on, namely that this statement introduces a local variable a and assigns its initial value the value of the in-parameter a.
The reason for not automatically allowing in-parameters to be used as local variables (which is allowed by many other languages, including C and Java) is that, in my experience, some people then get confused about the meaning of in-parameters in postconditions. An in-parameter mentioned in a postcondition refers to the value of the in-parameter passed in by the caller, and this is made clear by making in-parameters immutable inside the method body.
Rustan
Related
According to Rascal's documentation, the "?" operator can be used to query if a variable is "defined".
For example:
int u=1;
int v; // Defined but uninitialised
u = v?2;
v is uninitialised and therefore u will get the value 2.
However, doing this flags a "Warning: deprecated feature: run-time check on variable initialisation"
Hence the question, what is the non-deprecated way to do what the ? operator did in Rascal?
You can check with the IsDefined operator only things that can in principle be "undefined". Variables are not in that class; they were accidentally and now we are deprecating that behavior. In principle, there exists no null or undefined value in Rascal.
Having said that there are situations with maps and keyword fields of nodes and algebraic constructors where it is possible that a declared name does not exist at runtime. So:
myMap[myKey]?def; // a map does not have to have the key
myCons.myKeywordField?def ; // a keyword field does not have to be set
The isDefined operator is part of the assignment syntax on the left-hand side, as explained here: https://www.rascal-mpl.org/docs/Rascal/Statements/Assignment/IsDefined/
Also, the same syntax can be used as an expression: https://www.rascal-mpl.org/docs/Rascal/Expressions/Values/Boolean/IfDefinedElse/
Again, checking variables for undefinedness does not make sense since variables are always defined in Rascal. It is a static error otherwise. Defined but uninitialized variables are for making matching patterns look more elegant:
int i; int j; // here they are declared with a type
// here they are not defined and may not be used
if (<i, j> := <1,2>) { // here they are bound/defined
// here they can be used
}
// here i and j are not defined again and may not be used
I've been told in Java that I should avoid modifying the original parameters such as
public int doStuff(int begin, int end) {
/* loop or something */
begin++; //bad
end--; //also bad
/* end loop */
return
}
instead, I should do something like
public int doStuff(int begin, int end) {
int myBegin = begin; //something like this
int myEnd = end;
/* stuff */
return
}
So, I've been doing this in lua
function do_stuff(begin, last)
local my_begin = begin
local my_last = last
--stuff
my_begin = my_begin + 1
my_last = my_last - 1
--stuff
end
But, I'm wondering if
function do_stuff(begin, last)
--stuff
begin = begin + 1
last = last - 1
--stuff
end
is also discouraged, or is it nice and concise?
There are no rules. Let taste, clarity, and need decide.
Nevetheless, a common idiom is to provide default values for parameters as in
function log(x,b)
b = b or 10
...
end
If you were told not to modify the parameters of functions, then there was probably a reasoning associated with that. Whatever that reasoning is would apply as much to Lua as to Java, since they have similar function argument semantics. Those reasons could be one or more of (but not limited to):
If you modify a parameter... you don't have it anymore. If you suddenly have a need for the original value you were passed, it's gone now.
Creating confusion, depending on how the parameters are named. The word "begin" suggests the beginning of something. If you change it, it isn't necessarily the beginning anymore, but merely the current element you're operating on.
Creating potential errors, if dealing with reference types (non-basic types in Java, tables and such in Lua). When you modify an object, you're changing it for everyone. Whereas incrementing an integer is just changing your local value. So if you're frequently modifying parameters, you still need to think about which ones you ought to be poking at and which ones you shouldn't be.
To put it another way, if you agreed with the suggestion for doing so in Java, then it applies just as much to Lua. If you didn't agree with the suggestion in Java, then you have no more reason to follow it under Lua.
In Lua functions, threads, tables and userdata types are passed by reference. So unless you have one of those you are working with a local copy anyway.
So in your example:
function do_stuff(begin, last)
--stuff
begin = begin + 1
last = last - 1
--stuff
end
begin and last are local non-reference variables in do_stuff's scope.
The only reason to make a copy of them is that you might want to store there initial value for later use. For that purpose you can either create a backup copy of the initial value or you create a working copy of it. Whatever you prefer.
Only make sure you know what is passed by reference and what by value so you avoid changing things you don't want to change and the other way around.
Consider below struct:
typedef struct _Index {
NSInteger category;
NSInteger item;
} Index;
If I use this struct as a property:
#property (nonatomic, assign) Index aIndex;
When I access it without any initialization right after a view controller alloc init, LLDB print it as:
(lldb) po vc.aIndex
(category = 0, item = 0)
(lldb) po &_aIndex
0x000000014e2bcf70
I am a little confused, the struct already has valid memory address, even before I want to allocate one. Does Objective-C initialize struct automatically? If it is a NSObject, I have to do alloc init to get a valid object, but for C struct, I get a valid struct even before I tried to initialize it.
Could somebody explains, and is it ok like this, not manually initializing it?
To answer the subquestion, why you cannot assign to a structure component returned from a getter:
(As a motivation this is, because I have read this Q several times.)
A. This has nothing to do with Cbjective-C. It is a behavior stated in the C standard. You can check it for simple C code:
NSMakeSize( 1.0, 2.0 ).width = 3.0; // Error
B. No, it is not an improvement of the compiler. If it would be so, a warning would be the result, not an error. A compiler developer does not have the liberty to decide what an error is. (There are some cases, in which they have the liberty, but this are explicitly mentioned.)
C. The reason for this error is quite easy:
An assignment to the expression
NSMakeSize( 1.0, 2.0 ).width
would be legal, if that expression is a l-value. A . operator's result is an l-value, if the structure is an l-value:
A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,82) and is an lvalue if the first expression is an lvalue.
ISO/IEC 9899:TC3, 6.5.2.3
Therefore it would be assignable, if the expression
NSMakeSize( 1.0, 2.0 )
is an l-value. It is not. The reason is a little bit more complex. To understand that you have to know the links between ., -> and &:
In contrast to ., -> always is an l-value.
A postfix expression followed by the -> operator and an identifier designates a member of a structure or union object. The value is that of the named member of the object to which the first expression points, and is an lvalue. 83)
Therefore - that is what footnote 83 explains – ->, &, and . has a link:
If you can calculate the address of a structure S having a component C with the & operator, the expression (&S)->C is equivalent to S.C. This requires that you can calculate the address of S. But you can never do that with a return value, even it is a simple integer …
int f(void)
{
return 1;
}
f()=5; // Error
… or a pointer …
int *f(void)
{
return NULL;
}
f()=NULL; // Error
You always get the same error: It is not assignable. Because it is a r-value. This is obvious, because it is not clear,
a) whether the way the compiler returns a value, esp. whether he does it in address space.
b) when the time the life time of the returned value is over
Going back to the structure that means that the return value is a r-value. Therefore the result of the . operator on that is a r-value. You are not allowed to assign a value to a r-value.
D. The solution
There is a solution to assign to a "returned structure". One might decide, whether it is good or not. Since -> always is an l-value, you can return a pointer to the structure. Dereferencing this pointer with the -> operator has always an l-value as result, so you can assign a value to it:
// obj.aIndex returns a pointer
obj.aIndex->category = 1;
You do not need #public for that. (What really is a bad idea.)
The semantics of the property are to copy the struct, so it doesn't need to be allocated and initialized like an Objective-C object would. It's given its own space like a primitive type is.
You will need to be careful updating it, as this won't work:
obj.aIndex.category = 1;
Instead you will need to do this:
Index index = obj.aIndex;
index.category = 1;
obj.aIndex = index;
This is because the property getter will return a copy of the struct and not a reference to it (the first snippet is like the second snippet, without the last line that assigns the copy back to the object).
So you might be better off making it a first class object, depending on how it will be used.
Have this function defined in your module:
module Data
int inc(x) = x + 1;
Type this in the console:
rascal> import Data;
rascal> import List;
This works:
rascal> inc(1);
int: 2
But this does not:
rascal> list[int] y = [1,2,3];
rascal> mapper(y, inc);
|rascal://<path>|: insert into collection not supported on value and int
☞ Advice
But it works if inc(...)'s parameter type is declared:
int inc(int x) = x + 1;
So why does not having this type declaration work for using the inc(...) function directly, but not for passing that function to mapper(...)?
Because Rascal's type checker is still under development, you are not warned if you make a small mistake like forgetting to provide a type for a function parameter. It may still work, accidentally, in some circumstances but you are guaranteed to run into trouble somewhere as you've observed. The reason is that type inference for function parameters is simply not implemented as a feature. This is a language design decision with the intent of keeping error messages understandable.
So, this is not allowed:
int f(a) = a + 1;
And, it should be written like this:
int f(int a) = a + 1;
I consider it a bug that the interpreter doesn't complain about an untyped parameter. It is caused by the fact that we reuse the pattern matching code for both function parameters and inline patterns. [edit: issue has been registered at https://github.com/cwi-swat/rascal/issues/763]
In your case the example works because dynamically the type of the value is int and addition does not check the parameter types. The broken example breaks because the interpreter does checks the type of the function parameter at the call-site (which defaulted to value for the untyped parameter).
In the Lua manual we read:
A reference is a unique integer key.
As long as you do not manually add
integer keys into table t, luaL_ref
ensures the uniqueness of the key it
returns. You can retrieve an object
referred by reference r by calling
lua_rawgeti(L, t, r). Function
luaL_unref frees a reference and its
associated object.
Suppose I create a reference to an object, push it onto the API stack, save it under a global variable, and then call luaL_unref.... does it get freed despite being pointed to in Lua?
Example code:
lua_newtable( L );
int index = luaL_ref( L, LUA_REGISTRYINDEX );
lua_rawgeti( L, LUA_REGISTRYINDEX, index );
lua_setglobal( L, "test" );
luaL_unref( L, LUA_REGISTRYINDEX, index );
lua_getglobal( L, "test" ); // ...?
It would be.
Lua Registry is merely a table. No magic here.
So, your code is roughly equivalent to following (with exception of how lua_ref works with indices):
local t = { }
local index = #_R + 1 -- Assume that fictional _R is registry
_R[index] = t
_G["test"] = t -- Non-fictional _G is a global environment
_R[index] = nil
Also, note that your example does not make much sense. (I assume that it is oversimplified.) You don't need to put table into a registry before saving it as a global variable.
For your "unreferenced" table to be destroyed, you need GC to kick in. It cannot kick in between lua_newtable and lua_setglobal, if you call them one after another without returning control to Lua inbetween. Until you return control to Lua, your table is "referenced" in the Lua stack.
No, it is not explicitly freed.
I think there may be some confusion between the question and the previous answer.
The luaL_unref function merely unreferences the object, it does not actually perform a free operation. So if a variable still references the object it remains alive and is not freed.
The problem is with the wording of the reference. The associated object is "freed from the registry" but it is not "freed from the memory system".