In my program (full version on rise4fun), I want to slice an array, sort each slice, and then merge them back together.
I chose to use sequences because it makes slicing and merging very easy. Then, in order to reuse some existing code, I convert each slice to an array and call my implementation of insertion sort. But the call reports a call may violate context's modifies clause error. Why is that?
Here is the main portion of my code.
method MySort(input:array?<int>)
modifies input;
requires input != null;
requires input.Length > 0;
requires input.Length%2==0;
{
if(input.Length%2!=0){return;}
var mid:int := input.Length/2;
var subOne := input[0..mid];
var subTwo := input[mid..input.Length];
var arrSubOne := toArrayConvert(subOne);
var arrSubTwo := toArrayConvert(subTwo);
insertionSort(arrSubOne); //call may violate context's modifies clause
insertionSort(arrSubTwo); //call may violate context's modifies clause
}
method toArrayConvert(s:seq<int>) returns(a:array<int>)
requires |s|>0;
ensures |s| == a.Length;
ensures multiset(s[..]) == multiset(old(s[..]))
ensures forall i::0<=i<a.Length ==> s[i] == a[i];
{ /* ... */ }
method insertionSort(input:array?<int>)
modifies input
requires input != null
requires input.Length > 0
ensures perm(input,old(input))
ensures sortedBetween(input, 0, input.Length) // 0 to input.Length = whole input
{ /* ... */ }
You are missing a postcondition on toArrayConvert
ensures fresh(res)
Then your whole program verifies.
This postcondition guarantees that the array returned by that method is "fresh", meaning it is newly allocated. That allows Dafny to conclude that you are not modifying anything you're not supposed to: you're allowed to modify the array because you allocated it!
Please ask a separate question about the sequence swapping, or update your old question about that topic if you felt the answer was not sufficient.
The question is difficult to answer since you don't provide the contract of insertionSort. My guess is that insertionSort modifies more than it's caller, i.e. insertionSort lists some data in its modifies clauses that MySort doesn't list in its modifies clauses.
If this were allowed then a caller of MySort would "miss" potential modifications since, i.e. the contract of MySort would just be an under-approximation, which would be unsound.
Related
in short, the question is, I want to delete the last element of the DOUBLY LINKED LIST and I wrote this function...
fun deleteLast(){
if(isEmpty()){println("list is empty")}
if (head!=null && head?.nextNode == null){
head = null
}else {
tail = tail?.previousNode
tail?.nextNode = null
}
}
I went to the tail without traversing it and made its previous as new tail and new tail next(old tail) as null. And my result is desirable.
after writing this I pinged Google to check if this is right so, I found this...
void pop_back() {
if(this.head != null) {
//1. if head in not null and next of head
// is null, release the head
if(this.head.next == null) {
this.head = null;
} else {
//2. Else, traverse to the second last
// element of the list
Node temp = new Node();
temp = this.head;
while(temp.next.next != null)
temp = temp.next;
//3. Change the next of the second
// last node to null and delete the
// last node
Node lastNode = temp.next;
temp.next = null;
lastNode = null;
}
}
}
I want to ask If my code is right I just want you masters to review it. Thanks in advance!
The question only contains a snippet, not a minimal, reproducible example, so for the sake of argument (based on existing code and the comment) I'm going to assume that the full code looks something like this:
class Node<T>(var previousNode: Node<T>?, var nextNode: Node<T>?, var value: T)
class DoublyLinkedList<T>(var head: Node<T>?, var tail: Node<T>?) {
fun isEmpty() = head == null
// …other methods…
fun deleteLast(){
if(isEmpty()){println("list is empty")}
if (head!=null && head?.nextNode == null){
head = null
}else {
tail = tail?.previousNode
tail?.nextNode = null
}
}
}
Given this, it looks like your code is about right. There are a few points that could be addressed*, e.g.:
Inside the second if I think it needs to set tail to null as well, for safety.
Inside the second and third branches, you might want to set to null the previousNode and nextNode references in the node you're removing, for the benefit of any other code that still has a reference to it. (That might also give an extra hint to the garbage collector, though that shouldn't be needed.)
Instead of calling isEmpty(), it'd be simpler and more consistent to check whether head is null.
I'd add an else before the second if. As it is, the code works for an empty list, but that may be just luck; it'd be much more robust if neither of the other branches could be called on an empty list. (In some cases, this could let the compiler smart-cast head to non-nullable; but that doesn't happen here because it's mutable.)
In production code, you wouldn't print to stdout like that. If it's allowed to call deleteLast() on an empty list, then there's no need to print anything; if not (which would be more usual), you'd throw an exception. (And the method would have a doc comment explaining that.)
The formatting could be improved.
(* In my experience, any code can be improved — even code you've worked on many times before!)
However, you can't compare your code directly to the Google-sourced code, because it looks like that is for a singly-linked list.
A singly-linked list is a much simpler structure. All it has is a reference to the head node; that has a reference to the next node (and, presumably to the data stored in the node); and so on. So the only way to reach the end of the list is to traverse all the nodes, as the Google-sourced code does. (This also means there's often no point in having a separate class to represent the list as a whole; a reference to the first node is all you need. Many operations can be written concisely with recursive methods. You can also make it immutable, which has many advantages; that's the primary data structure in some languages.)
Your list, though, has a direct reference to the last node, which of course avoids the need to traverse the entire list to find it. As your code demonstrates, this means that some operations are much more efficient in double-linked lists. There are corresponding disadvantages, though: each node takes more memory; there are more references to update when changing the list; it's easier for the list to get into an inconsistent state; and it's less suitable for an immutable list.)
If I have a Role R defined as:
role R { method answer { 42 } }
What is the difference (if any) between these two lines:
my $a = 'question' does R;
my $b = 'question' but R;
They appear very similar:
say $a.answer; # OUTPUT: «42»
say $b.answer; # OUTPUT: «42»
say $a.WHAT; # OUTPUT: «(Str+{R})»
say $b.WHAT; # OUTPUT: «(Str+{R})»
Is this a case of there being More Than One Way To Do It™, and these both mean the same thing? Or is there a subtle difference that I'm missing?
note:
I understand that does is both an operator and a trait and thus can be used when for compile-time mixins (e.g., class C does R {}) whereas but is only for runtime mixins. I also understand that but can be used with an object (e.g., my $c = 'question' but False) whereas does can only be used with a Role. I'm not asking about either of those differences; my only question is about whether there's a difference when both are used at runtime with a Role. I have read the documentation section on mixing in Role, but didn't see an answer.
Put simply:
does modifies an object in place (and should be used with caution with value types, see note below)
but returns a new object.
When created off of a literal, it's probably not as evident, but when used with another object, it's pretty clear I think:
role R { method answer { 42 } }
my $question = 'question';
my $but = $question but R;
my $does = $question does R;
say $question.WHAT; # (Str+{R})
say $but.WHAT; # (Str+{R})
say $does.WHAT; # (Str+{R})
say $question.WHERE; # 129371492039210
say $but.WHERE; # 913912490323923
say $does.WHERE; # 129371492039210 <-- same as $question's
Notice I cheated a bit and swapped the order of does and but. If I had preserved the order you had, the does would modify $question in place, applying the role, meaning that but would clone $question (with its role) and apply the role (again!):
my $does = $question does R;
my $but = $question but R;
say $does.WHAT; # (Str+{R})
say $but.WHAT; # (Str+{R}+{R})
This is because does as an operator is conceptually akin to ++ or +=, that is, designed to be used in a standalone context, for instance
my $foo = …;
given $bar {
when 'a' { $foo does A }
when 'b' { $foo does B }
when 'c' { $foo does B }
}
Using but is conceptually closer to using $foo + 1 — mostly meaningless unless assigned to or passed to something else.
A warning for does and value types
If you use does on a value type (strings, numbers mainly), there is an extremely high likelihood that you will cause unintended side effects. This is because value types (which, e.g., strings are) are supposed to be immutable and substitutable for one other. Note the following:
role Fooish { }
my $foo = 'foo';
$foo does Fooish;
say 'foo'.WHAT; # (Str+{Fooish})
This is a substitution that's happening at compile time (so it won't affect, e.g, 'foobar'.substr(0,3), that happens at runtime), but can cause some truly weird effects if you toss them in a loop:
role Fooish { }
my #a;
#a.push('foo' does Fooish) for ^10;
say #a[0].WHAT; # (Str+{Fooish}+{Fooish}+{Fooish}+{Fooish}+{Fooish}
+{Fooish}+{Fooish}+{Fooish}+{Fooish}+{Fooish})
Applying multiple rolls takes longer and longer the more you do it, so if you change that to ^100000, be ready to wait a while. OTOH, doing but gives you nice constant time and doesn't pollute the literal. This behavior seems, AFAICT, to be perfectly valid, but definitely something that can catch you unexpectedly.
Is there a special name for doing assignment in a conditional? Here is an example of what I am asking about in C:
// Assume a and b have been previously defined and are compatible types
if( (a = b) ) { // <- What do you call that?
//do something
}
A couple friends of mine and I are convinced that there is a name for it, and some other people have agreed that there is one, but we can't find it anywhere. Has anyone here ever heard a term for it?
Assuming that an assignment is intentional, there is no special name for this. C language specification places a very weak requirement on the controlling expression of an if statement:
6.8.4.1-1: The controlling expression of an if statement shall have scalar type.
An assignment expression satisfies this requirement, as long as a and b are scalar. An implicit comparison to zero is performed on the result of this assignment:
6.8.4.1-2: In both forms, the first substatement is executed if the expression compares unequal to 0. In the else form, the second substatement is executed if the expression compares equal to 0.
Note that compilers would issue a warning when they see an assignment like that, because missing second = is a common source of errors. You can prevent these warnings using parentheses, as described in this Q&A.
It doesn’t really have a name, though people do call it various things. If the code follows your question:
if( a = b )...
then common terms are: bug, error, etc. However if b is not a variable but an expression, e.g. as in the common C patterns:
if( (c = getchar()) != EOF )...
while( *q++ = *p++ )...
then it might be called an idiom, pattern, etc.
I don’t know if it has a name but I’d call it “useful feature that nobody understands”.
It is very useful indeed.
We can consider it a slang.
In C++ for example you can use this by declaring a variable directly, and this is useful for safety checks:
if (Object *a = takeObject()) {
// a is not nullptr
}
Or when I don’t want to repeat a statement in a loop:
while (a = next()) {
}
Instead of:
a = next();
while (a) {
a = next();
}
But commonly these are just mistakes which compilers like gcc and clang give warnings about (and they force you to put an horrible double tuple to silence the warning ew!).
This question already has an answer here:
How to modify/partially remove a range from a BTreeMap?
(1 answer)
Closed 6 years ago.
I'm trying to translate some simple data structures I use in C++ over to Rust, starting with an interval tree, but I don't understand how to modify my underlying data structure (here an std::collections::BTreeSet) during iteration - essentially so I can merge overlapping entries as they appear.
If I use the standard idiom for iterating over a collection, I get the following message about it being immutable "cannot borrow self.storage as mutable because it is also borrowed as immutable", and there doesn't appear to be an option to get a mutable iterator that I can see ... what am I missing?
C++ code:
inline void Insert(const Interval& interval)
{
auto it = storage.insert(interval);
// check to see if we overlap the previous element,
// if we do, start our merge loop from there
if (it != begin()) {
const_iterator prev = std::prev(it);
if (prev->Overlaps(*it)) it = prev;
}
while (it != end()) {
const_iterator nx = std::next(it);
if (nx != end() && it->Overlaps(*nx)) {
const Interval u = it->Union(*nx);
it = storage.erase(it);
it = storage.erase(it);
it = storage.insert(it, u);
} else
break;
}
}
Rust code:
/// Add a new interval into the tree
pub fn insert(&mut self, other: Interval) -> () {
self.storage.insert(other);
for int in self.storage.iter() {
if other <= *int {
break
} else if other.overlaps(int) {
self.storage.remove(&other);
self.storage.remove(int);
self.storage.insert(other.union(int).unwrap());
}
}
}
You cannot mutate a BTreeSet while you're iterating on it – that would invalidate the iterator. Unfortunately, unlike C++, Rust doesn't have insert or remove methods that return updated iterators (and if it did, they would have to be methods on the iterator itself).
BTreeSet doesn't offer a mutable iterator, because the only additional operation you could do is obtain a mutable reference to the elements in the set. However, doing this could potentially screw up the set's ordering, so it's not available.
The most straightforward solution is to build a list of operations to perform during the iteration, then perform them once the iteration is complete. However, for this algorithm, this won't quite work, since you might need to merge an interval that is the result of a previous merge. So, once you've found a pair of intervals to merge, you need to keep track of the relevant values, break out of the iteration, perform the merge, then restart the iteration. BTreeSet provides a range method that lets you iterate over a subset of the set's values, so you might want to use that instead of iter, which always iterates over all the values. However, range is unstable as of Rust 1.8, so you'll need a nightly compiler to be able to use it.
According to the Go reference there are two ways of declaring a variable
Variable_declarations (in the format of var count = 0 or var count int)
and
Short_variable_declarations (in the format of count := 0)
I found it's very confusing to decide which one to use.
The differences I know (till now) are that:
I can only using a count := 0 format when in the scope of a function.
count := 0 can be redeclared in a multi-variable short declaration.
But they do behave the same as far as I know. And in the reference it also says:
It (the count:=0way) is shorthand for a regular variable declaration with initializer expressions but no types
My confusions are:
If one is just the shorthand way of the other, why do they behave differently?
In what concern does the author of Go make two ways of declaring a variable (why are they not merged into one way)? Just to confuse us?
Is there any other aspect that I should keep my eyes open on when using them, in case I fall into a pit?
The Variable declarations make it clear that variables are declared. The var keyword is required, it is short and expresses what is done (at the file level everything excluding comments has to start with a keyword, e.g. package, import, const, type, var, func). Like any other block, variable declarations can be grouped like this:
var (
count int
sum float64
)
You can't do that with Short variable declarations. Also you can use Variable declarations without specifying the initial value in which case each variable will have the zero value of its type. The Short variable declaration does not allow this, you have to specify the initial value.
One of Go's guiding design principle was to make the syntax clean. Many statements require or it is handy that they allow declaring local variables which will be only available in the body of the statement such as for, if, switch etc. To make the syntax cleaner and shorter, Short variable declaration is justified in these cases and it is unambigous what they do.
for idx, value := range array {
// Do something with index and value
}
if num := runtime.NumCPU(); num > 1 {
fmt.Println("Multicore CPU, cores:", num)
}
Another difference: Redeclaration
Quoting from the Language specification:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
This one is also handy. Suppose you want to do proper error handling, you can reuse an err variable because most likely you only need it to check if there were any errors during the last function call:
var name = "myfile.txt"
fi, err := os.Stat(name) // fi and err both first declared
if err != nil {
log.Fatal(err)
}
fmt.Println(name, fi.Size(), "bytes")
data, err := ioutil.ReadFile(name) // data is new but err already exists
// so just a new value is assigned to err
if err != nil {
log.Fatal(err)
}
// Do something with data