Templates in Rust are checked for correctness prior to their instantiation, so there is a clear separation between errors in the template itself (which should not be if you use someone else's / library template) and in the place of instantiation, where all that is required of you is to meet the requirements for type described in the template:
trait Sortable {} fn sort<T: Sortable>(array: &mut [T]) {} fn main() { sort(&mut [1,2,3]); }
import std.traits; // auto sort(T)(T[] array) {} - guard auto sort(T)(T[] array) if(isFloatingPoint!T) {} void main() { sort([1,2,3]); }
source / main.d (27): Error: template main.sort cannot deduce function from argument types! () (int []), candidates are:
source / main.d (23): main.sort (T) (T [] array) if (isFloatingPoint! T)
template Sortable(T) { // , , swap enum Sortable = __traits(compiles, swap(T.init, T.init)); // static assert(Sortable, "Sortable isn't implemented for "~T.stringof~". swap function isn't defined."); } auto sort(T)(T[] array) if(Sortable!T) {} void main() { sort([1,2,3]); }
source / main.d (41): Error: static assert “Sortable is not implemented for int. swap function not defined. "
source / main.d (44): instantiated from here: Sortable! int
source / main.d (48): instantiated from here: sort! ()
import std.c.stdlib; void main() { auto x = cast(int*)malloc(int.sizeof); // scope scope(exit) free(x); // free(x); *x = 0; }
*** Error in `demo ': double free or corruption (fasttop): 0x0000000001b02650 ***
Rust version:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
import std.stdio; int* bar(int* p) { return p; } int* foo(int n) { return bar(&n); } void main() { int* p1 = foo(1); int* p2 = foo(2); writeln(*p1, ",", *p2); }
2.2
Error: cannot be taken function safe
import std.stdio; ref int bar(ref int p) { return p; } ref int foo(int n) { return bar(n); } void main() { auto p1 = foo(1); auto p2 = foo(2); writeln(p1, ",", p2); }
1.2
C ++
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
import std.stdio; int minval(int[] A) { int currmin = void; // undefined behavior foreach(a; A) if (a < currmin) currmin = a; return currmin; } void main() { auto A = [1,2,3]; int min = minval(A); writeln(min); }
A more idiomatic (and working) version of this function would look like this:
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
int minval(int[] A) { return A.reduce!"a < b ? a : b"; // //return A.reduce!((a,b) => a < b ? a : b); }
C ++
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
struct A { int *x; this(int v) { x = new int; *x = v; } } void main() { auto a = A(1); auto b = a; *bx = 5; assert(*ax == 1); // fails }
this(this) // this { // auto newx = new int; *newx = *x; x = newx; }
Rust will not do anything behind your back. Want an automatic implementation of Eq or Clone? Simply add the deriving property to your structure:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
Gives us:2.2
struct X { int a, b; } void swap_from(ref X x, const ref X y) { xa = yb; xb = ya; } void main() { auto x = X(1,2); swap_from(x, x); writeln(xa, ",", xb); }
import std.stdio; void main() { int[] v; v ~= 1; v ~= 2; foreach(val; v) { if(val < 5) { v ~= 5 - val; } } writeln(v); }
[1, 2, 4, 3]
import std.stdio; import std.container; void main() { DList!int v; v.insert(1); v.insert(2); foreach(val; v[]) // [] range { if(val < 5) { v.insertFront(5 - val); v.insertBack(5 - val); } } writeln(v[]); }
[3, 4, 1, 2, 4, 3]
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
Gives us a "2". In Rust zhy you are obliged to list all the options when comparing with the sample. In addition, the code does not automatically jump to the next option unless it encounters a break.
import std.stdio; enum Color {RED, BLUE, GRAY, UNKNOWN} Color color = Color.GRAY; void main() { int x; final switch(color) { case Color.GRAY: x = 1; case Color.RED: case Color.BLUE: x = 2; } writeln(x); }
source / main.d (227): Error: enum member UNKNOWN is not represented in final switch
source / main.d (229): Warning: switch case fallthrough - use 'goto case;' if intended
source / main.d (229): Warning: switch case fallthrough - use 'goto case;' if intended
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
In Rust, you must enclose the bodies of cycles and comparisons in braces. A trifle, of course, but less a class error.
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
It spawns several resources instead of one:
doneresource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
import std.concurrency; import std.stdio; class Resource { private int* value; int* acquire() { if(!value) { value = new int; } return value; } } void foo(shared Resource res) { // Error: non-shared method main.Resource.acquire is not callable using a shared object writeln("resource ", res.acquire); } void main() { auto res = new shared Resource(); foreach(i; 0..5) { spawn(&foo, res); } writeln("done"); }
synchronized class Resource { private int* value; shared(int*) acquire() { if(!value) { value = new int; } return value; } }
done
resource 7FDED3805FF0
resource 7FDED3805FF0
resource 7FDED3805FF0
resource 7FDED3805FF0
resource 7FDED3805FF0
Source: https://habr.com/ru/post/225507/
All Articles