How to extend a Vec<String> as HashMap value? - vector

I have a HashMap<String, Vec<String>>. I cannot figure out how to update the value by growing the Vec. I thought the following would work:
fn add_employee(mut data: HashMap<String, Vec<String>>) -> HashMap<String, Vec<String>> {
loop {
println!("Please enter the name of the employee you would like to manage.");
let mut employee = String::new();
io::stdin().read_line(&mut employee).expect(
"Failed to read line",
);
let employee = employee.trim();
let mut department = String::new();
println!("Please enter the name of the department you would like to add the employee to.");
io::stdin().read_line(&mut department).expect(
"Failed to read line",
);
let department = department.trim();
data.entry(department.to_string())
.extend(vec![employee.to_string()])
.or_insert(vec![employee.to_string()]);
}
}
but it instead gives the error
error: no method named `extend` found for type `std::collections::hash_map::Entry<'_, std::string::String, std::vec::Vec<std::string::String>>` in the current scope
--> src/main.rs:27:14
|
27 | .extend(vec![employee.to_string()])
| ^^^^^^

After thinking about the entry API a little more I came up with the following solution:
let val = data.entry(department.to_string())
.or_insert(vec!());
val.extend(vec!(employee.to_string()));

Use this code:
use std::collections::hash_map::Entry;
match data.entry(department.to_string()) {
Entry::Occupied(mut entry) => { entry.get_mut().push(employee.to_string()); },
Entry::Vacant(entry) => { entry.insert(vec!(employee.to_string())); },
}
If the key exists, get a mutable reference on the value and add the new string,
Else, create a new vector and insert it in the hashmap.
All this information is in the documentation.

Related

Cannot reach to members of an array with index

I am trying to fill an array with data from Firebase. But after filling the array I can't call its' members from their index. I am filling the array by this function
func loadSounds(){
Firestore.firestore().collection("data").getDocuments{ (snapshot, error) in
if error == nil{
for document in snapshot!.documents{
let name = document.data()["name"] as? String ?? "error"
let sounds = document.data()["sounds"] as? [String : [String : Any]]
var soundsArray = [dataSound]()
if let sounds = sounds{
for sound in sounds {
let soundName = sound.value["name"] as? String ?? "error"
let soundImage = sound.value["image"] as? String ?? "error"
soundsArray.append(dataSound(name: soundName , image: soundImage ))
}
}
categoriesArray.append(Category(category: name , sounds: soundsArray))
}
print(categoriesArray[0].category)
} else {
print(error)
}
} }
When I try to access it from View, It gives index out of bounds error.
struct ContentView: View {
init(){
loadSounds()
}
var body: some View {
Text(categoriesArray[0].category)}}
If I try to access it via ForEach, it works, also when I try to print it from loadSounds function it works, but I need to access them from their index in View. Thanks for any help.
Never access items of an array by index in the rendering area of a SwiftUI View, in almost all cases the array is empty when the view is rendered the first time.
In your case use .first and handle the optional
var body: some View {
Text(categoriesArray.first?.category ?? "No value")}} // or empty string

How can I implement batching in FSharp.Data.GraphQL?

I am building a GraphQL server using F# with .NET Core. To implement batching and address N+1 select, I am building a data loader. The Facebook's dataloader uses Node.js event loop tick to collect and dispatch batched requests.
However, such mechanism is not available in .NET Core. I know I can implement run/dispatch method from the data loader instance which can be called manually. But, that is something very hard to do from within the resolvers which execute independently. So I need some auto dispatching mechanism to run the batched requests.
Any suggestions on how to achieve it?
This is a great question, which I recently hit myself.
There are a few "data-loader" type libraries for F# and .NET, however if you are also using FSharp.Data.GraphQL then there are fewer solutions that integrate well.
Note that the "Haxl" approach will not work (easily) with FSharp.Data.GraphQL. This is because the Haxl types must be integrated into GraphQL query models, but FSharp.Data.GraphQL only understands sync and async.
The most suitable implementation that I could find is in FSharp.Core.Extensions. This is fairly new library, but it's high quality and Apache 2.0 licensed.
I'm sure there are many ways it can be integrated it into FSharp.Data.GraphQL, however my preferred approach was to put the data-loaders into the root value of the schema. This allows all GraphQL resolvers down the tree to access it.
I think the best way to explain it is to show an example.
Here we have a domain of "People" who can have zero or more "followers", who are also "People". Each person has a globally unique ID. There is significant overlap in the followers between people, so a naive solution may re-fetch the same data repeatedly. Our database layer can fetch many person records in one query, so we would like to leverage that where possible.
You can paste this code into an .fsx file and run it. The dependencies are fetched by Paket.
paket.dependencies
generate_load_scripts: true
source https://www.nuget.org/api/v2
source https://api.nuget.org/v3/index.json
storage: none
framework: net5.0, netstandard2.1
nuget FSharp.Core 5.0.0
nuget FSharp.Data.GraphQL.Server 1.0.7
github Horusiath/fsharp.core.extensions:0ff5753bb6f232e0ef3c446ddcc72345b74174ca
DataLoader.fsx
#load ".paket/load/net50/FSharp.Data.GraphQL.Server.fsx"
#load "paket-files/Horusiath/fsharp.core.extensions/src/FSharp.Core.Extensions/Prolog.fs"
#load "paket-files/Horusiath/fsharp.core.extensions/src/FSharp.Core.Extensions/AsyncExtensions.fs"
type Person =
{
ID : string
Name : string
}
// Mocks a real database access layer
module DB =
// Used to avoid interleaving of printfn calls during async execution
let private logger = MailboxProcessor.Start (fun inbox -> async {
while true do
let! message = inbox.Receive()
printfn "DB: %s" message
})
let private log x =
logger.Post(x)
// Our data-set
let private people =
[
{ ID = "alice"; Name = "Alice" }, [ "bob"; "charlie"; "david"; "fred" ]
{ ID = "bob"; Name = "Bob" }, [ "charlie"; "david"; "emily" ]
{ ID = "charlie"; Name = "Charlie" }, [ "david" ]
{ ID = "david"; Name = "David" }, [ "emily"; "fred" ]
{ ID = "emily"; Name = "Emily" }, [ "fred" ]
{ ID = "fred"; Name = "Fred" }, []
]
|> Seq.map (fun (p, fs) -> p.ID, (p, fs))
|> Map.ofSeq
let fetchPerson id =
async {
log $"fetchPerson {id}"
match people |> Map.find id with
| (x, _) -> return x
}
let fetchPersonBatch ids =
async {
let idsString = String.concat "; " ids
log $"fetchPersonBatch [ {idsString} ]"
return
people
|> Map.filter (fun k _ -> Set.contains k ids)
|> Map.toSeq
|> Seq.map (snd >> fst)
|> Seq.toList
}
let fetchFollowers id =
async {
log $"fetchFollowers {id}"
match people |> Map.tryFind id with
| Some (_, followerIDs) -> return followerIDs
| _ -> return []
}
// GraphQL type definitions
open FSharp.Core
open FSharp.Data.GraphQL
open FSharp.Data.GraphQL.Types
#nowarn "40"
[<NoComparison>]
type Root =
{
FetchPerson : string -> Async<Person>
FetchFollowers : string -> Async<string list>
}
let rec personType =
Define.Object(
"Person",
fun () -> [
Define.Field("id", ID, fun ctx p -> p.ID)
Define.Field("name", String, fun ctx p -> p.Name)
Define.AsyncField("followers", ListOf personType, fun ctx p -> async {
let root = ctx.Context.RootValue :?> Root
let! followerIDs = root.FetchFollowers p.ID
let! followers =
followerIDs
|> List.map root.FetchPerson
|> Async.Parallel
return Seq.toList followers
})
])
let queryRoot = Define.Object("Query", [
Define.AsyncField(
"person",
personType,
"Fetches a person by ID",
[
Define.Input("id", ID)
],
fun ctx root -> async {
let id = ctx.Arg("id")
return! root.FetchPerson id
})
])
// Construct the schema once to cache it
let schema = Schema(queryRoot)
// Run an example query...
// Here we fetch the followers of the followers of the followers of `alice`
// This query offers many optimization opportunities to the data-loader
let query = """
query Example {
person(id: "alice") {
id
name
followers {
id
name
followers {
id
name
followers {
id
name
}
}
}
}
}
"""
let executor = Executor(schema)
async {
// Construct a data-loader for fetch person requests
let fetchPersonBatchFn (requests : Set<string>) =
async {
let! people =
requests
|> DB.fetchPersonBatch
let responses =
Seq.zip requests people
|> Map.ofSeq
return responses
}
let fetchPersonContext = DataLoader.context ()
let fetchPersonLoader = DataLoader.create fetchPersonContext fetchPersonBatchFn
// Construct a data-loader for fetch follower requests
let fetchFollowersBatchFn (requests : Set<string>) =
async {
let! responses =
requests
|> Seq.map (fun id ->
async {
let! followerIDs = DB.fetchFollowers id
return id, followerIDs
})
|> Async.Parallel
return Map.ofSeq responses
}
let fetchFollowersContext = DataLoader.context ()
let fetchFollowersLoader =
DataLoader.create fetchFollowersContext fetchFollowersBatchFn
let root =
{
FetchPerson = fun id -> fetchPersonLoader.GetAsync(id)
FetchFollowers = fun id -> fetchFollowersLoader.GetAsync(id)
}
// Uncomment this to see how sub-optimal the query is without the data-loader
// let root =
// {
// FetchPerson = DB.fetchPerson
// FetchFollowers = DB.fetchFollowers
// }
// See https://bartoszsypytkowski.com/data-loaders/
do! Async.SwitchToContext fetchPersonContext
do! Async.SwitchToContext fetchFollowersContext
// Execute the query
let! response = executor.AsyncExecute(query, root)
printfn "%A" response
}
|> Async.RunSynchronously

Can't use Vec two times and I can't borrow it instead

I attempted to implement the Rosetta Code password generator:
extern crate rand;
use rand::prelude::*;
fn main() {
println!("Hello, world!");
let p = generate_password(12, 5);
for i in p.iter() {
println!("{:?}", i);
}
}
fn generate_password(length: i32, number: i32) -> Vec<Vec<String>> {
let lowercase = "abcdefghijklmnopqrstuvwxyz";
let uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let listnumber = "0123456789";
let other = "!\\\"#$%&'()*+,-./:;<=>?#[]^_{|}~";
let all: Vec<char> = String::from(format!("{}{}{}{}", lowercase, uppercase, listnumber, other))
.chars()
.collect();
let mut password: Vec<String> = Vec::new();
let mut password_list: Vec<Vec<String>> = Vec::new();
for num in 1..number {
for l in 1..length {
password.push(String::from(thread_rng().choose(&all).unwrap().to_string()));
}
password_list.push(&password);
}
return password_list;
}
Rust won't allow me to use either borrowed value or direct value:
error[E0308]: mismatched types
--> src/main.rs:26:28
|
26 | password_list.push(&password);
| ^^^^^^^^^
| |
| expected struct `std::vec::Vec`, found reference
| help: consider removing the borrow: `password`
|
= note: expected type `std::vec::Vec<std::string::String>`
found type `&std::vec::Vec<std::string::String>`
The help message says I should remove the borrow because of type mismatch but it's still got an error after removing it because the value has been moved.
You've declared a type to be Vec<Vec<String>>, but you're trying to store a reference inside it.
When you remove the reference, you're getting a different error because push takes ownership of the value, so the original variable can no longer be used. But you then try to use it in the subsequent loop. The easy fix is to declare the variable inside the loop, so it is a new variable each time:
let mut password_list = Vec::new();
for num in 1..number {
let mut password = Vec::new();
for l in 1..length {
password.push(String::from(thread_rng().choose(&all).unwrap().to_string()));
}
password_list.push(password);
}
Note that you don't need a lot of the type annotations, especially on local function variables. The compiler can infer them, which makes the code a lot cleaner.

Could not cast value of type '__NSDictionaryM' (0x1111152b0) to 'FIRDataSnapshot' Firebase Swift 3

I am trying to read nested data structures from Firebase Database, but I don't know how to manage the case when an object of type [String:AnyObject] could be nil.
When readFeesCleaner(callback_) is called, it throws an error.
func readFeesCleaner(callback: #escaping ((_ feesCleaner: FeesCleaner) -> Void)) {
dbRef.child("FeesCleaner").child(self.uidOfTextField!).observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in
guard !(snapshot.value is NSNull) else {
return
}
//throws error: signal SIGABRTCould not cast value of type '__NSDictionaryM' (0x1111152b0) to 'FIRDataSnapshot' (0x10ef16d18).
let feesCleanersReceived = FeesCleaner(snapshot: (snapshot.value)! as! FIRDataSnapshot)
callback(feesCleanersReceived)
}) { (error:Error) in
print(#line, "\(error.localizedDescription)")
}
}
struct FeesCleaner {
var outstandingFees: AnyObject!
var timeStampFeesSaved: [String:AnyObject]!
var backgroundCheck: AnyObject!
init(
outstandingFees: AnyObject? = nil, //value might not exist when reading
timeStampFeesSaved: [String:AnyObject]? = nil,// value might not exist when reading
backgroundCheck: AnyObject) {
self.outstandingFees = outstandingFees
self.timeStampFeesSaved = timeStampFeesSaved
self.backgroundCheck = backgroundCheck
}//end of init
//read data here
[full struct data here][1]
https://gist.github.com/bibscy/dc48f7107459379e045a50fdbbc35335
}//end of struct
There's a number of issues here. First:
how to manage the case when an object of type [String:AnyObject]
could be nil.
You've handled that with the prior statement, noting that you can also add
if snapshot.exists == false {return}
Second: You've got to handle optionals properly - if a var could be nil, you need code in place to handle that situation and not plow through it. If you force unwrap an optional you are essentially stating that for sure, it will never be nil, so basically, don't do that.
One fix could be to simply pass the snapshot as a DataSnapshot and then pull out the properties one at a time; if they exist, assign them, if not set to 0 or nil or some other placeholder.
Something like this inside the Firebase closure:
let feesCleanersReceived = FeesCleaner(withSnapshot: snapshot)
and then your struct like this: note we are leveraging the nil coalescing operator, ??
struct FeesCleanerStruct {
var outstandingFees: String?
var timeStampFeesSaved: String?
init(withSnapshot: DataSnapshot) {
let dict = withSnapshot.value as! [String: Any]
self.outstandingFees = dict["outstandingFees"] as? String ?? "0.0"
self.timeStampFeesSaved = dict["timeStampFeesSaved"] as? String ?? "0"
}
}

Unable to return a vector of string slices: borrowed value does not live long enough

I'm new to Rust and I'm having some trouble with the borrow checker. I don't understand why this code won't compile. Sorry if this is close to a previously answered question but I can't seem to find a solution in the other questions I've looked at.
I understand the similarity to Return local String as a slice (&str) but in that case it is just one string being returned and not enough for me to reason with my code in which I am trying to return a vector. From what I understand, I am trying to return references to str types that will go out of scope at the end of the function block and so should I be mapping that vector of &str into a vector of String? I am not so concerned about the performance effects of converting &str to String. First I'd just like to get it working.
This is the code, the error is in the lex function.
use std::io::prelude::*;
use std::fs::File;
use std::env;
fn open(mut s: &mut String, filename: &String) {
let mut f = match File::open(&filename) {
Err(_) => panic!("Couldn't open file"),
Ok(file) => file,
};
match f.read_to_string(&mut s) {
Err(_) => panic!("Couldn't read file"),
Ok(_) => println!("File read successfully"),
};
}
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ")
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list
}
fn main() {
let args: Vec<_> = env::args().collect();
if args.len() < 2 {
panic!("Please provide a filename");
} else {
let ref filename = args[1];
let mut s = String::new();
open(&mut s, filename);
let token_list: Vec<&str> = lex(&s);
println!("{:?}", token_list);
}
}
Here is the error message
error: borrowed value does not live long enough
self.0.borrow().values.get(idx)
^~~~~~~~~~~~~~~
reference must be valid for the anonymous lifetime #1 defined on the block at 23:54...
pub fn value(&self, idx: usize) -> Option<&Value> {
^
note: ...but borrowed value is only valid for the block at 23:54
pub fn value(&self, idx: usize) -> Option<&Value> {
^
I'm finding it hard to reason with this code because with my level of experience with Rust I can't visualise the lifetimes of these variables. Any help would be appreciated as I've spent an hour or two trying to figure this out.
The problem is that you're allocating a new String (token_string) inside the lex function and then returning an array of references to it, but token_string will get dropped (and the memory freed) as soon as it falls out of scope at the end of the function.
fn lex(s: &String) -> Vec<&str> {
let token_string: String = s.replace("(", " ( ") // <-- new String allocated
.replace(")", " ) ");
let token_list: Vec<&str> = token_string.split_whitespace()
.collect();
token_list // <-- this is just an array of wide pointers into token_string
} // <-- token_string gets freed here, so the returned pointers
// would be pointing to memory that's already been dropped!
There's a couple of ways to address this. One would be to force the caller of lex to pass in the buffer that you want to use to collect into. This would change the signature to fn lex<'a>(input: &String, buffer: &'a mut String) -> Vec<&'a str> This signature would specify that the lifetimes of the returned &strs will be at least as long as the lifetime of the buffer that's passed in.
Another way would be to just return a Vec<String> instead of Vec<&str> if you can tolerate the extra allocations.

Resources