I need structures with fixed maximum size, so the obvious choice seem to be arrayvec crate. However, I'm stuck when ArrayVec is a member of a structure that later needs to be partially initialised:
use arrayvec::ArrayVec; // 0.4.7
#[derive(Debug)]
struct Test {
member_one: Option<u32>,
member_two: ArrayVec<[u16; 5]>,
}
pub fn main() {
let mut test = Test {
member_one: Some(45678),
member_two: [1, 2, 3], // <- What to do here to initialise only 3 elements?
};
print!("{:?}", test);
}
I'd like to initialise the first three elements of the ArrayVec as it's perfectly capable of holding any number of elements from zero to 5 (in my example), but I can't figure out how to do it.
You can collect into an ArrayVec from an iterator:
let mut test = Test {
member_one: Some(45678),
member_two: [1, 2, 3].into_iter().collect(),
};
ArrayVec does not offer a one-step method to do this. Instead, create the ArrayVec and then add values to it, in any of the ways you can add values:
let mut member_two = ArrayVec::new();
member_two.extend([1, 2, 3].iter().cloned());
let test = Test {
member_one: Some(45678),
member_two,
};
Related
I have a combo ReScript and TypeScript project. I want to use gentype to expose TypeScript friendly objects. Gentype works for string, bool, records, and other basic objects without any hassles. How can I work with list and char and other ReScript-specific types from TypeScript?
There is a shims feature but I don't know how to do that. I would assume there are built-in shims for the standard Belt library but can't find them.
I plan to do most of the calculations and heavy-lifting inside Rescript. So when the info is sent to TypeScript, I'll probably just be consuming the data, not modifying it. This might be iterating through a list to display the contents in a non-Rescript React project. I don't plan to manipulate the data.
One option is to convert lists to arrays inside ReScript before exporting the results. So any time I want to consume information from TypeScript, I'll create a function and/or type in ReScript that only has bool, number, string, array, and object. I could create an "interop" module with all the stuff I want to consume or use from TypeScript. This provides a clean separation between the ReScript and TypeScript world and is easy to get my head around but seems a little inefficient (like converting all lists to arrays) and extra work.
On the other hand, if using the Belt objects like list and map is cumbersome from TypeScript, even with the shims, then I'm probably better off creating my "interop" module anyway.
What is the recommended/simplest/best way to use list, map, char, and other ReScript specific objects from within TypeScript? Are there friendly Typescript definitions for the Belt standard library that I could use even if I wasn't using ReScript?
===
One additional note. I have experience trying to use F# (functional) from C#. It was painful. The best solution for me in that environment was to create an interface on the F# side that was easily consumable on the C# side that did not use the F# native objects.
As rescript compiles to JavaScript, and the output is very readable and (usually) straight-forward, you could just emulate what it generates.
For example, this rescript code:
let xs = list{1, 2, 3}
let _ = List.map(x => x + 1, xs)
is compiled into this (slightly simplified) JavaScript:
var List = require("./stdlib/list.js");
var xs = {
hd: 1,
tl: {
hd: 2,
tl: {
hd: 3,
tl: /* [] */0
}
}
};
List.map((x) => x + 1, xs);
There is a slight problem with the literal syntax of lists specifically, but that could be simplified a bit by using List.cons instead:
let xs = List.cons(1, List.cons(2, List.cons(3, list{})))
which becomes:
var xs = List.cons(1, List.cons(2, List.cons(3, /* [] */0)));
Pattern matching also isn't as convenient, obviously, but still pretty straight-forward for the simple things at least. For example:
let rec sum = xs => switch xs {
| list{} => 0
| list{x, ...rest} => x + sum(rest)
}
becomes:
function sum(xs) {
if (xs) {
return xs.hd + sum(xs.tl);
} else {
return 0;
}
}
Most other types don't have any special compiler support, and so becomes just plain function calls. Using Belt.Map for example, despite using some advanced language features, compiles to very straight-forward JavaScript:
module IntCmp = Belt.Id.MakeComparable({
type t = int
let cmp = (a, b) => a - b
})
let m = Belt.Map.make(~id=module(IntCmp))
let _ = Belt.Map.set(m, 0, "a")
becomes (more or less):
var Belt_Id = require("./stdlib/belt_Id.js");
var Belt_Map = require("./stdlib/belt_Map.js");
var IntCmp = Belt_Id.MakeComparable({
cmp: (a, b) => a - b
});
var m = Belt_Map.make(IntCmp);
Belt_Map.set(m, 0, "a");
I know how to iterate over a HashMap in Rust, however, I am a little confused about how this works in memory. How do we iterate over values that are not stored sequentially in memory? A detailed explanation of the code below at the heap and stack level would be much appreciated.
use std::collections::HashMap;
let name = vec![String::from("Charlie"), String::from("Winston"), String::from("Brian"), String::from("Jack")];
let age = vec![50, 5, 7, 21];
let mut people_ages: HashMap<String, i32> = name.into_iter().zip(age.into_iter()).collect();
for (key, value) in &people_ages {
println!("{}: {}", key, value);
}
At the end of the intro of the documentation, it is mentioned that the implementation relies on a C++ implementation of SwissTables.
This page contains illustrations about two variants: « flat » and « node » based.
The main difference between these two variants is pointer stability.
In the « node » based version, the key-value pairs, once inserted, keep their address in memory even if the hash is reorganised.
In the « flat » version, some insertions/removals can make the previous key-value pairs be moved in memory.
When it comes to the Rust implementation, I am not experienced enough to be certain of any specific detail, but I tried this simple example based on yours.
use std::collections::HashMap;
fn main() {
let name = vec![
String::from("Charlie"),
String::from("Winston"),
String::from("Brian"),
String::from("Jack"),
];
let age = vec![50, 5, 7, 21];
let mut people_ages: HashMap<String, i32> =
name.into_iter().zip(age.into_iter()).collect();
let mut keys = Vec::new();
let mut values = Vec::new();
for (key, value) in &people_ages {
keys.push(key);
values.push(value);
let key_addr = key as *const String as usize;
let value_addr = value as *const i32 as usize;
println!("{:x} {:x} {}: {}", key_addr, value_addr, key, value);
}
// people_ages.insert("Bob".to_owned(), 4); // mutable and immutable borrow
println!("keys: {:?}", keys);
println!("values: {:?}", values);
}
/*
55e08ff8bd40 55e08ff8bd58 Brian: 7
55e08ff8bd20 55e08ff8bd38 Charlie: 50
55e08ff8bd00 55e08ff8bd18 Winston: 5
55e08ff8bce0 55e08ff8bcf8 Jack: 21
keys: ["Brian", "Charlie", "Winston", "Jack"]
values: [7, 50, 5, 21]
*/
The commented out line (insertion) is rejected because we cannot alter the hashmap while keeping references to its content.
Thus, I guess (I'm not certain) that the implementation does not rely on the « node » based variant since we cannot take benefit of the pointer stability it provides (due to the ownership model in Rust), and probably it relies on the « flat » variant.
This means that we can expect that the key-value pairs associated with the same hash are tightly packed in memory, and iterating over them should be very similar to iterating over a vector: regular progression (with some skips however) very friendly with cache prefetch.
Printing the addresses tends to confirm that guess (however the test is not complete enough), and shows a backward progression.
I have an enum type in my Rust program of which some variants may contain inner data.
enum MyEnum {
A,
B(u64),
C(SmallStruct),
D(Box<LargeStruct>)
}
This enum is going to be stored tens of thousands of times and memory usage is an issue. I would like to avoid accidentally adding a very large variant for the enum. Is there a way that I can tell the compiler to limit the size of an enum instance in memory?
As of Rust 1.57 you can use asserts in a const context, so this kind of check will work:
// assert that MyEnum is no larger than 16 bytes
const _ASSERT_SMALL: () = const_assert(mem::size_of::<MyEnum>() <= 16);
Playground
Original answer follow for historical reference.
As noted in the other answer, you can use the const_assert! macro, but it will require an external crate, static_assertions. If you're looking for a std-only solution and can live with the uglier error message when the assertion fails, you can use this:
#[deny(const_err)]
const fn const_assert(ok: bool) {
0 - !ok as usize;
}
// assert that MyEnum is no larger than 16 bytes
const _ASSERT_SMALL: () = const_assert(mem::size_of::<MyEnum>() <= 16);
Playground
You can read about this technique, along with ways to improve it, in the article written by the author of the static_assertions crate.
EDIT: Link to original article is non-functional, web archive version
You could use const_assert! and mem::size_of to assert that your enum is less than or equal to a certain size.
I'm trying to use the _.filter property to filter an array. I'd like to use the matchesProperty shorthand, but don't want to do a straight comparison.
eg. This works:
.each(.filter(this.across, ['len', 3]), dostuff);
but if I want to filter values less than 9, I need to use a function:
.each(.filter(this.across, function (o) {return o.len<9}), dostuff);
Is there a neater way to do this?
I don't know what dostuff and this.across are, but let's assume you have an array of objects with property len and you want to filter values less than 9.
You can do this in a point free functional style, with just lodash, but it's going to look more convoluted than if you just use an arrow function. The matchesProperty shorthand only works for equality comparison, so can't be used in this case.
See both options below:
const arr = [
{ len: 2 }, // keep
{ len: 5 }, // keep
{ len: 9 },
{ len: 22 },
{ len: 8 } // keep
]
// point free functional style
const filtered = _.filter(arr, _.flow(_.property('len'), _.partial(_.gt, 9)))
// with arrow function
const filtered2 = _.filter(arr, o => o.len < 9)
console.log(filtered)
console.log(filtered2)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
I am attempting to sort a CSV file by specifying which column order to sort in:
for example: ./csort 3, 1, 5 < DATA > SORTED_DATA
or ./csort 3, 4, 6, 2, 1, 5 < DATA ...
example line of DATA: 177,27,2,42,285,220
I used a vector split(string str) function to store the columns specified in the arguments which require sorting. Creating a vector:
vector<string> columns {3, 1, 5}; // for example
Not entirely sure how to use this columns vector to proceed with the sorting process; though, I am aware that I could use sort.
sort(v.begin(), v.end(), myfunction);
As I understand your question, you have already parsed your data into 4 vectors, 1 vector per column, and you want to be able to sort your data, specifying the prececedence of the column to sort -- i.e. sort by col1, then col3, then col4...
What you want to do isn't too difficult, but you'll have to backtrack a bit. There are multiple ways to approach the problem, but here's a rough outline. Based on the level of expertise you exhibit in your question, you might have to look a few terms in the following outline, but if you do you'll have a good flexible solution to your problem.
You want to store your data by row, since you want to sort rows... 4 vector for 4 columns won't help you here. If all 4 elements in the row are going to be a the same type, you could use a std::vector or std::array for the row. std::array is solid if # cols is known compile time, std::vector for runtime. If the types are inhomogeneous, you could use a tuple, or a struct. Whatever type you use, let's call it RowT.
Parse and store into your rows, make a vector of RowT.
Define a function-object which provides the () operator for a left and right hand side of RowT. It must implement the "less than operation" following the precedence you want. Lets call that class CustomSorter.
Once you have that in place, your final sort will be:
CustomSorter cs(/*precedence arguments*/);
std::sort(rows.begin(), rows.end(), cs);
Everything is really straightforward, a basic example can bee seen here in the customsort example. In my experience the only part you will have to work at is the sort algorithm itself.
The easiest way is to use a class that has a list of indexes as a member, and go through the list in order to see if the item is less than the other.
class VecLess
{
std::vector<int> indexes;
public:
VecLess(std::vector<int> init) : indexes(init)
{
}
bool operator()(const std::vector<string> & lhs, const std::vector<string> rhs)
{
for (auto i = indexes.begin(); i != indexes.end(); ++i)
{
if (lhs[*i] < rhs[*i])
return true;
if (rhs[*i] < lhs[*i])
return false;
}
return false;
}
};