Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
$ rustc --version
rustc 0.11.0-pre (6266f64 2014-06-06 23:06:35 -0700)
host: x86_64-unknown-linux-gnu
$ rustc nbody.rs --opt-level 3
$ dmd --help
DMD64 D Compiler v2.065
$ dmd -ofnbody source/nbody.d -release -inline -noboundscheck -O
$ gdc --version
gdc (GCC) 4.8.2
$ gdc -onbody source/nbody.d -O3 -frelease
$ ldc2 --version
LDC - the LLVM D compiler (0.13.0-beta1):
based on DMD v2.064 and LLVM 3.4.1
Default target: x86_64-unknown-linux-gnu
$ ldc2 -ofnbody source/nbody.d -release -O3
/usr/bin/time --verbose ./nbody 50000000

TreeMap, так и HashMap). Длинная дискуссия тут, но основной смысл — что NaN не вписывается. В Rust пока консенсус таков, чтобы сделать обёркти для f32 и f64, которые реализуют способности Ord и Hash, так что могут быть и ключами.D> bool[double] map;
=> map
D> map[0.0/0.0] = true;
D> map.keys
=> [-nan]
D> map[-double.nan]
=> true
D> auto val = double.nan;
=> val
D> typeid(double).getHash(&val)
=> 360911136610280172
float как ключей в D:10:02 SiegeLord: So I checked, D associative arrays in the current release treat NaN's as equal, and in the master they treat them as unequal (i.e. they do the bad thing)
10:02 SiegeLord: The bad thing being, I think you can insert key NaNs, but not get them back
10:03 SiegeLord: So… essentially… that code example is nothing to be proud of
10:04 kvark: SiegeLord: so it works in 99.9% of cases, where we don't have a NaN key, and the rest of the cases are simply unable to get the key back? That sounds like a win to me
10:04 SiegeLord: It's a DoS vector
10:04 pczarn: why?
10:05 SiegeLord: You make insertion operation be O(n)
10:05 SiegeLord: Keep inserting NaN, and it keeps making the bucket longer and longer
10:05 SiegeLord: And it has to check them all by equality before determining that its a 'new' key
10:09 pyon Why would anyone want to compare floats for equality? This is a data type invented for scientific computations with inexact numbers. :-|
import std.stdio;
import std.datetime;
void dos(bool[float] array)
{
array[double.nan] = true;
}
void main()
{
bool[float] array;
auto test1 = benchmark!(() => dos(array))(100_000); array.clear;
auto test2 = benchmark!(() => dos(array))(1000_000); array.clear;
auto test3 = benchmark!(() => dos(array))(10000_000);
writeln(test1[0].msecs / cast(double) 100_000); // 0.00038
writeln(test2[0].msecs / cast(double) 1000_000); // 0.000307
writeln(test3[0].msecs / cast(double) 10000_000); // 0.0002816
}
<?php
function a($a) {
$a["add"]=1;
return $a;
}
var_dump(a(array("o"=>2)));
var_dump(a(array("c"=>4)));
?>array(2) { ["o"]=> int(2) ["add"]=> int(1) } array(2) { ["c"]=> int(4) ["add"]=> int(1) }use std::collections::hashmap::HashMap;
type MyMap = HashMap<String,int>;
fn a(mut map: MyMap) -> MyMap {
map.insert("add".to_string(), 1);
map
}
fn main() {
let mut x: MyMap = HashMap::new();
x.insert("o".to_string(), 2);
println!("{}", a(x));
x = HashMap::new();
x.insert("c".to_string(), 4);
println!("{}", a(x));
}
.to_string()?insert(), а не []?add?x = HashMap::new() память первого массива полностью освобождается? А в конце main освобождается и второй? А теперь хитрее: представим, что мы копируем из одного массива данные в другой. И ключи у них ну очень длинные, мегабайты длинной. Как будет работать такая процедура? Ключи будут дублироваться в памяти, или будет вестись счетчик ссылок на одинаковые строки и удалятся эти строки будут только когда их более никто не использует?&str, а ассоциативному массиву нужен String. Фактически to_string() выделяет память в куче и копирует туда строку. Не всегда нужно иметь строку в куче, поэтому по умолчанию Rust не делает ничего лишнего.Rc:use std::rc::Rc;
fn foo(_x: Rc<String>) {}
fn main() {
let x = Rc::new("my long string".to_string());
foo(x.clone());
}
auto& a(const std::unordered_map<std::string, int>& arr)
{
arr["add"] = 1;
return arr;
}
for(auto& el: a({{"o", 2}}))
std::cout << el.first << " => " << el.second;
for(auto& el: a({{"c", 4}}))
std::cout << el.first << " => " << el.second;
import std.stdio;
// Возврат из функции
int[string] add(int[string] array)
{
array["add"] = 1;
return array;
}
// Измененение будет видно вне функции
void add2(int[string] array)
{
array["add"] = 1;
}
void main()
{
writeln(add(["o": 2])); // ["add":1, "o":2]
writeln(add(["c": 4])); // ["c":4, "add":1]
// еще вариант записи
writeln(["o": 2].add); // ["add":1, "o":2]
// или даже так
["o": 2].add.writeln; // ["add":1, "o":2]
// Демонстрация поведения by-reference
int[string] arr = ["o": 2];
add2(arr);
writeln(arr); // ["add":1, "o":2]
}
["o":2], изменялся бы локальный ассоциативный массив внутри функции. Такое поведение имеют статические массивы:// статический массив
void add(int[5] array)
{
// заполним весь массив значением 42
array[] = 42;
}
// динамический массив
void add(int[] array)
{
// заполним весь массив значением 42
array[] = 42;
}
void main()
{
int[5] array = [1, 2, 3, 4, 5];
add(array);
writeln(array); // [1, 2, 3, 4, 5]
add(array[]);
writeln(array); // [42, 42, 42, 42, 42]
}
add(array[]), через оператор [ ] (оператор для slicing) мы получаем динамический массив, который внутри ссылается на данные статического массива.int[string] arrayarray["add"] = 1;add(["o": 2])
string[float] map0;
double[string][string] map1;
bool[bool][string][float] map2;
map0[42.0] = "foo";
assert(42.0 in map0);
map1["foo"]["bar"] = 42.0;
foreach(k1, submap; map1)
foreach(k2, val; submap)
std.stdio.writeln(k1, " ", k2, " ", val);
assert(map0.keys == [42.0]);
assert(map0.values == ["foo"]);
const hash_t toHash();
const bool opEquals(ref const KeyType s);
const int opCmp(ref const KeyType s);
int minval(int[] A)
{
return A.reduce!"a < b ? a : b";
// или
//return A.reduce!((a,b) => a < b ? a : b);
}Лучше так:
int minval(int[] A)
{
return A.reduce!q{ a < b ? a : b };
}#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)]
struct A{
x: Box<int>
}Аналога данного механизма в D нет.
Есть же:
struct A {
mixin Clone!A;
mixin Eq!A;
mixin Hash!A;
mixin PartialEq!A;
mixin PartialOrd!A;
mixin Ord!A;
mixin Show!A;
int x;
}
Сравнение D и C++ и Rust на примерах