Loading pageā¦
Rust walkthroughs
Loading pageā¦
{"args":{"content":"# How does smallvec::SmallVec::from_vec differ from smallvec::smallvec! macro for initialization?
from_vec converts an existing Vec into a SmallVec, potentially avoiding allocation if the data fits within the inline capacity, while smallvec! is a macro that constructs a SmallVec directly from element values with syntax similar to vec!. The key difference is input source: from_vec takes ownership of a pre-existing vector (useful when you have data already in a Vec), while smallvec! creates a SmallVec from individual elements (useful for literals and direct construction). Use from_vec when converting from Vec or when data already exists in vector form, and smallvec! for inline construction similar to how you'd use vec!.
use smallvec::SmallVec;
fn main() {
// smallvec! creates SmallVec from elements
let sv: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3, 4];
// Similar to vec! syntax
let v = vec![1, 2, 3, 4];
// smallvec! with type annotation for inline capacity
// [i32; 4] means: inline array of i32 with capacity 4
let sv_inline: SmallVec<[i32; 8]> = smallvec::smallvec![1, 2, 3];
// Elements are constructed directly into SmallVec
// No intermediate Vec allocation if elements fit inline
println!(\"SmallVec: {:?}\", sv);
}smallvec! constructs SmallVec directly from elements.
use smallvec::SmallVec;
fn main() {\n // from_vec converts existing Vec to SmallVec\n let vec = vec![1, 2, 3, 4, 5];\n let sv: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n \n // If elements exceed inline capacity, heap is used\n // Original Vec's heap allocation may be reused\n \n println!(\"SmallVec: {:?}\", sv);\n \n // from_vec is useful when you already have a Vec\n fn process_data(data: Vec<i32>) -> SmallVec<[i32; 16]> {\n SmallVec::from_vec(data)\n }\n \n let result = process_data(vec![10, 20, 30]);\n println!(\"Processed: {:?}\", result);\n}from_vec converts an existing Vec into a SmallVec.
use smallvec::SmallVec;
fn main() {
n // smallvec! with elements fitting inline capacity\n let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n // Stored inline, no heap allocation\n \n // smallvec! with elements exceeding inline capacity\n let sv2: SmallVec<[i32; 2]> = smallvec::smallvec![1, 2, 3, 4, 5];\n // Elements don't fit, heap allocated\n \n // from_vec with elements fitting inline\n let vec1 = vec![1, 2, 3];\n let sv3: SmallVec<[i32; 4]> = SmallVec::from_vec(vec1);\n // Vec's allocation freed, elements moved to inline storage\n \n // from_vec with elements exceeding inline\n let vec2 = vec![1, 2, 3, 4, 5];\n let sv4: SmallVec<[i32; 2]> = SmallVec::from_vec(vec2);\n // Vec's heap allocation may be reused\n \n println!(\"All created successfully\");\n}Both handle inline capacity, but from_vec may reuse existing heap allocation.
use smallvec::SmallVec;
fn main() {\n // smallvec! for empty SmallVec\n let empty1: SmallVec<[i32; 4]> = smallvec::smallvec![];\n \n // from_vec requires a Vec\n let empty2: SmallVec<[i32; 4]> = SmallVec::from_vec(Vec::new());\n \n // from_vec is more verbose for empty case\n // smallvec! is cleaner for empty initialization\n \n // Alternative: SmallVec::new()\n let empty3: SmallVec<[i32; 4]> = SmallVec::new();\n \n println!(\"Empty SmallVecs created\");\n}smallvec![] is cleaner for empty initialization; from_vec(Vec::new()) is verbose.
use smallvec::SmallVec;
fn main() {\n // smallvec! supports repeat syntax like vec!\n let sv1: SmallVec<[i32; 10]> = smallvec::smallvec![0; 5];\n // Creates [0, 0, 0, 0, 0]\n \n // from_vec would require:\n let sv2: SmallVec<[i32; 10]> = SmallVec::from_vec(vec![0; 5]);\n \n // Both produce same result\n assert_eq!(sv1, sv2);\n \n println!(\"Repeated elements: {:?}\", sv1);\n}smallvec! supports vec!-like repeat syntax; from_vec requires creating Vec first.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! directly constructs elements\n // If elements fit inline: no allocation\n // If too many: allocates on heap\n \n let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n // Fits inline: no heap allocation\n \n // from_vec: Vec already has allocation\n // If elements fit inline: Vec allocation freed\n // If too many: Vec's allocation may be reused\n \n let vec = vec![1, 2, 3];\n let sv2: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n // Vec's allocation freed, elements moved inline\n \n let vec = vec![1, 2, 3, 4, 5, 6, 7, 8];\n let sv3: SmallVec<[i32; 2]> = SmallVec::from_vec(vec);\n // Elements exceed inline capacity\n // Vec's heap allocation may be transferred to SmallVec\n \n println!(\"SmallVecs created\");\n}from_vec may reuse Vec's heap allocation when elements exceed inline capacity.
use smallvec::SmallVec;
fn main() {\n // from_vec is useful when you receive a Vec from elsewhere\n fn process(input: Vec<String>) -> SmallVec<[String; 8]> {\n SmallVec::from_vec(input)\n }\n \n // from_vec from iterator (requires Vec intermediate)\n let sv1: SmallVec<[i32; 4]> = SmallVec::from_vec(\n (0..5).collect()\n );\n \n // Alternative: SmallVec::from_iter (no Vec intermediate)\n let sv2: SmallVec<[i32; 4]> = (0..5).collect();\n \n // from_iter is more efficient than from_vec for iterators\n // But from_vec is useful when you already have a Vec\n \n println!(\"Converted collections\");\n}from_vec is useful for converting existing Vec; use from_iter for iterators.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! may be slightly faster for inline cases\n // because elements are constructed directly\n \n // from_vec for inline: Vec allocation + free\n // smallvec! for inline: direct construction\n \n // For heap cases:\n // from_vec: may reuse Vec's allocation\n // smallvec!: always allocates new\n \n use std::time::Instant;\n \n let iterations = 100_000;\n \n // Measure smallvec!\n let start = Instant::now();\n for _ in 0..iterations {\n let _: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n }\n let smallvec_time = start.elapsed();\n \n // Measure from_vec\n let start = Instant::now();\n for _ in 0..iterations {\n let _: SmallVec<[i32; 4]> = SmallVec::from_vec(vec![1, 2, 3]);\n }\n let from_vec_time = start.elapsed();\n \n println!(\"smallvec!: {:?}\", smallvec_time);\n println!(\"from_vec: {:?}\", from_vec_time);\n // smallvec! is typically faster for inline cases\n // because no Vec allocation is needed\n}smallvec! avoids intermediate Vec allocation; from_vec includes Vec overhead.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! advantages:\n // - Concise syntax similar to vec!\n // - Direct construction, no intermediate Vec\n // - Compile-time element checking\n // - Clear for literals and constants\n \n // from_vec advantages:\n // - Works with existing Vec\n // - Function call, not macro\n // - Works with dynamic data\n // - Can transfer heap allocation\n \n // Use smallvec! for literals\n let literal: SmallVec<[&str; 4]> = smallvec::smallvec![\"a\", \"b\", \"c\"];\n \n // Use from_vec for dynamic data\n let dynamic: Vec<i32> = get_data();\n let sv: SmallVec<[i32; 8]> = SmallVec::from_vec(dynamic);\n \n // Use from_vec when converting\n fn convert_small_vec(input: Vec<u8>) -> SmallVec<[u8; 32]> {\n SmallVec::from_vec(input)\n }\n \n println!(\"Created SmallVecs\");\n}\n\nfn get_data() -> Vec<i32> {\n vec![1, 2, 3, 4, 5]\n}Use smallvec! for literals, from_vec for existing Vec.
use smallvec::SmallVec;\n\nfn main() {\n // Both can grow beyond inline capacity\n \n // smallvec! starts inline, may grow to heap\n let mut sv1: SmallVec<[i32; 2]> = smallvec::smallvec![1, 2];\n sv1.push(3); // Now on heap\n \n // from_vec: if Vec is large, may already be on heap\n let mut sv2: SmallVec<[i32; 2]> = SmallVec::from_vec(vec![1, 2, 3, 4]);\n // Already on heap (exceeded inline capacity of 2)\n sv2.push(5); // Still on heap, allocation may be reused\n \n println!(\"sv1: {:?}\", sv1);\n println!(\"sv2: {:?}\", sv2);\n}Both handle growing beyond inline capacity; from_vec may reuse existing allocation.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! requires type annotation for inline capacity\n let sv1: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n \n // from_vec also needs type annotation or inference\n let vec = vec![1, 2, 3];\n let sv2: SmallVec<[i32; 4]> = SmallVec::from_vec(vec);\n \n // Both need explicit type for inline capacity\n // Compiler can't infer inline capacity from usage\n \n // Function can provide type inference\n fn make_smallvec() -> SmallVec<[i32; 8]> {\n smallvec::smallvec![1, 2, 3]\n }\n \n fn from_small_vec(v: Vec<i32>) -> SmallVec<[i32; 8]> {\n SmallVec::from_vec(v)\n }\n \n println!(\"Type inference works with function signatures\");\n}Both require explicit type annotation for inline capacity.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! moves elements into SmallVec\n let strings: SmallVec<[String; 4]> = smallvec::smallvec![\n String::from(\"a\"),\n String::from(\"b\"),\n ];\n // Elements moved directly\n \n // from_vec takes ownership of Vec\n let vec = vec![String::from(\"a\"), String::from(\"b\")];\n let sv: SmallVec<[String; 4]> = SmallVec::from_vec(vec);\n // vec is consumed, its elements moved\n \n // Both result in owned elements in SmallVec\n // Neither clones elements\n \n println!(\"SmallVecs own their elements\");\n}Both take ownership of elements; no cloning involved.
use smallvec::SmallVec;\n\nfn main() {\n // smallvec! works with generic types\n let sv1: SmallVec<[Option<i32>; 4]> = smallvec::smallvec![Some(1), None, Some(3)];\n \n // from_vec works with any Vec<T>\n let vec: Vec<Option<i32>> = vec![Some(1), None, Some(3)];\n let sv2: SmallVec<[Option<i32>; 4]> = SmallVec::from_vec(vec);\n \n // Both handle complex types equally\n \n // Nested SmallVecs\n type Inner = SmallVec<[i32; 4]>;\n let nested: SmallVec<[Inner; 2]> = smallvec::smallvec![\n smallvec::smallvec![1, 2],\n smallvec::smallvec![3, 4],\n ];\n \n println!(\"Generic types work with both\");\n}Both support any element type; use whichever is convenient.
rust\nuse smallvec::SmallVec;\n\nfn main() {\n // smallvec! macro\n // - Syntax: smallvec![elem1, elem2, ...]\n // - Creates SmallVec directly from elements\n // - Supports repeat syntax: smallvec![value; count]\n // - No intermediate Vec allocation for inline\n // - Good for: literals, constants, inline construction\n // - Macro invocation, not function call\n \n // SmallVec::from_vec\n // - Syntax: SmallVec::from_vec(vec)\n // - Converts existing Vec to SmallVec\n // - Takes ownership of Vec\n // - May reuse Vec's heap allocation\n // - Good for: converting from Vec, dynamic data\n // - Function call\n \n // Alternative: SmallVec::from_iter\n // - Syntax: iter.collect() or SmallVec::from_iter(iter)\n // - No intermediate Vec\n // - Good for: converting from iterators\n \n let from_macro: SmallVec<[i32; 4]> = smallvec::smallvec![1, 2, 3];\n let from_vec: SmallVec<[i32; 4]> = SmallVec::from_vec(vec![1, 2, 3]);\n let from_iter: SmallVec<[i32; 4]> = (1..=3).collect();\n \n assert_eq!(from_macro, from_vec);\n assert_eq!(from_macro, from_iter);\n}\n\n\nChoose based on data source: literal elements vs. existing Vec vs. iterator.
vec!-like syntax\n- Constructs SmallVec directly from elements\n- Supports repeat syntax: smallvec![value; count]\n- No intermediate allocation for inline cases\n- Clean syntax for literals and constants\n- Compile-time element validation\n\nfrom_vec characteristics:\n- Function that converts Vec<T> to SmallVec<T, N>\n- Takes ownership of existing Vec\n- May reuse Vec's heap allocation for large data\n- Useful when data already in Vec\n- Works with dynamically constructed data\n- No macro needed\n\nAllocation behavior:\n- smallvec!: Constructs elements directly; if they fit inline, no allocation\n- from_vec: If elements fit inline, Vec allocation freed; if too many, Vec allocation may be reused\n- For inline-fitting data, smallvec! avoids allocation entirely\n- For large data, from_vec may avoid reallocation by reusing Vec's buffer\n\nUse smallvec! when:\n- Creating SmallVec from literal elements\n- Inline construction with known values\n- Writing constants or static values\n- Clean, vec!-like syntax desired\n- Elements are constructed inline\n\nUse from_vec when:\n- Converting existing Vec to SmallVec\n- Data comes from a function returning Vec\n- Dynamic construction completed in Vec\n- Want to potentially reuse heap allocation\n- Avoiding macro invocation\n\nAlternatives:\n- SmallVec::new(): Empty SmallVec\n- SmallVec::from_iter(): From iterator, no Vec intermediate\n- SmallVec::with_capacity(): Pre-allocate capacity\n\nKey insight: The choice between smallvec! and from_vec depends on where your data originates. If you're constructing a SmallVec from scratch with known elements, smallvec! is more ergonomic and potentially more efficientāit constructs elements directly into the SmallVec without an intermediate Vec. If you already have a Vec (perhaps from another function or from collecting an iterator), from_vec converts it efficiently and may reuse the existing heap allocation when the data exceeds inline capacity. For iterators, prefer SmallVec::from_iter() or .collect() over from_vec to avoid the intermediate Vec entirely. The smallvec! macro's repeat syntax (smallvec![value; count]) provides additional convenience for initializing with repeated values, mirroring vec! behavior.","path":"/articles/287_smallvec_from_vec_vs_macro.md"},"tool_call":"file.create"}