pull/8/head
Claus Matzinger 2019-10-08 14:47:50 +02:00
rodzic 2c9cc73d6a
commit 1f2005fa07
5 zmienionych plików z 48 dodań i 373 usunięć

Wyświetl plik

@ -139,52 +139,6 @@ impl<T> List<T> where T: Sized + Clone {
.value .value
}) })
} }
///
/// Splits off and returns `n` nodes as a `List<T>`.
///
/// # Arguments
///
/// `n: usize` - The number of elements after which to split the list.
///
/// # Panics
///
/// Panics when:
/// - The list is empty
/// - `n` is larger than the length
///
/// # Example
///
/// ```
/// # use testing::List;
///
/// let mut list = List::new_empty();
/// list.append(12);
/// list.append(11);
/// list.append(10);
/// let mut list2 = list.split(1);
/// assert_eq!(list2.pop(), Some(12));
/// assert_eq!(list.pop(), Some(11));
/// assert_eq!(list.pop(), Some(10));
/// ```
///
pub fn split(&mut self, n: usize) -> List<T> {
// Don't do this in real life. Use Results, Options, or anything that
// doesn't just kill the program
if self.length == 0 || n >= self.length - 1 {
panic!("That's not working");
}
let mut n = n;
let mut new_list = List::new_empty();
while n > 0 {
new_list.append(self.pop().unwrap());
n -= 1;
}
new_list
}
} }
impl <T>Drop for List<T> where T: Clone + Sized { impl <T>Drop for List<T> where T: Clone + Sized {
@ -248,25 +202,4 @@ mod tests {
assert_eq!(list.length, 0); assert_eq!(list.length, 0);
assert_eq!(list.pop(), None); assert_eq!(list.pop(), None);
} }
#[test]
fn test_list_split() {
let mut list = List::new_empty();
list.append(1);
list.append(1);
list.append(1);
list.append(1);
list.append(1);
assert_eq!(list.length, 5);
let list2 = list.split(3);
assert_eq!(list.length, 2);
assert_eq!(list2.length, 3);
}
#[test]
#[should_panic]
fn test_list_split_panics() {
let mut list: List<i32> = List::new_empty();
let _ = list.split(3);
}
} }

Wyświetl plik

@ -1,24 +1,22 @@
use std::io::{Write, Read}; use std::io::{Read, Write};
// Structs // Structs
/// ///
/// Configuration for our application /// Configuration for our application
/// ///
pub struct Config { pub struct Config {
values: Vec<(String, String)> values: Vec<(String, String)>,
} }
/// ///
/// A service for managing a configuration /// A service for managing a configuration
/// ///
pub struct KeyValueConfigService { pub struct KeyValueConfigService {}
}
// Traits // Traits
/// ///
/// Provides a get() function to return valuse associated with /// Provides a get() function to return values associated with
/// the specified key. /// the specified key.
/// ///
pub trait ValueGetter { pub trait ValueGetter {
@ -43,16 +41,13 @@ pub trait ConfigReader {
impl Config { impl Config {
pub fn new(values: Vec<(String, String)>) -> Config { pub fn new(values: Vec<(String, String)>) -> Config {
Config { Config { values: values }
values: values
}
} }
} }
impl KeyValueConfigService { impl KeyValueConfigService {
pub fn new() -> KeyValueConfigService { pub fn new() -> KeyValueConfigService {
KeyValueConfigService { KeyValueConfigService {}
}
} }
} }
@ -74,12 +69,13 @@ impl ConfigReader for KeyValueConfigService {
let values: Vec<(String, String)> = buffer let values: Vec<(String, String)> = buffer
.split_terminator("\n") // split .split_terminator("\n") // split
.map(|line| line.trim()) // remove whitespace .map(|line| line.trim()) // remove whitespace
.filter(|line| { // filter invalid lines .filter(|line| {
let pos = line.find("=") // filter invalid lines
.unwrap_or(0); let pos = line.find("=").unwrap_or(0);
pos > 0 && pos < line.len() - 1 pos > 0 && pos < line.len() - 1
}) })
.map(|line| { // create a tuple from a line .map(|line| {
// create a tuple from a line
let parts = line.split("=").collect::<Vec<&str>>(); let parts = line.split("=").collect::<Vec<&str>>();
(parts[0].to_string(), parts[1].to_string()) (parts[0].to_string(), parts[1].to_string())
}) })
@ -90,16 +86,16 @@ impl ConfigReader for KeyValueConfigService {
impl ValueGetter for Config { impl ValueGetter for Config {
fn get(&self, s: &str) -> Option<String> { fn get(&self, s: &str) -> Option<String> {
self.values.iter() self.values.iter().find_map(|tuple| {
.find_map(|tuple| if &tuple.0 == s { if &tuple.0 == s {
Some(tuple.1.clone()) Some(tuple.1.clone())
} else { } else {
None None
}
}) })
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -112,7 +108,6 @@ mod tests {
assert_eq!(config.get("HELLO"), None); assert_eq!(config.get("HELLO"), None);
} }
#[test] #[test]
fn keyvalueconfigservice_write_config() { fn keyvalueconfigservice_write_config() {
let config = Config::new(vec![("hello".to_string(), "world".to_string())]); let config = Config::new(vec![("hello".to_string(), "world".to_string())]);
@ -121,20 +116,27 @@ mod tests {
let mut target = vec![]; let mut target = vec![];
assert!(service.write(config, &mut target).is_ok()); assert!(service.write(config, &mut target).is_ok());
assert_eq!(String::from_utf8(target).unwrap(), "hello=world\n".to_string()); assert_eq!(
String::from_utf8(target).unwrap(),
"hello=world\n".to_string()
);
} }
#[test] #[test]
fn keyvalueconfigservice_read_config() { fn keyvalueconfigservice_read_config() {
let service = KeyValueConfigService::new(); let service = KeyValueConfigService::new();
let readable = &format!("{}\n{}", "hello=world", "a=b").into_bytes(); let readable = &format!("{}\n{}", "hello=world", "a=b").into_bytes();
let config = service.read(&mut Cursor::new(readable)) let config = service
.read(&mut Cursor::new(readable))
.expect("Couldn't read from the vector"); .expect("Couldn't read from the vector");
assert_eq!(config.values, vec![ assert_eq!(
config.values,
vec![
("hello".to_string(), "world".to_string()), ("hello".to_string(), "world".to_string()),
("a".to_string(), "b".to_string())]); ("a".to_string(), "b".to_string())
]
);
} }
} }

Wyświetl plik

@ -1,7 +1,5 @@
#![feature(test)] #![feature(test)]
//pub mod list;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
extern crate test; extern crate test;

Wyświetl plik

@ -1,261 +0,0 @@
//!
//! A simple singly-linked list for the Rust-Cookbook by Packt Publishing.
//!
//! Recipes covered in this module:
//! - Documenting your code
//! - Testing your documentation
//! - Writing tests and benchmarks
//!
#![doc(html_logo_url = "https://blog.x5ff.xyz/img/main/logo.png",
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
use std::cell::RefCell;
use std::rc::Rc;
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
#[derive(Clone)]
struct Node<T> where T: Sized + Clone {
value: T,
next: Link<T>,
}
impl<T> Node<T> where T: Sized + Clone {
fn new(value: T) -> Rc<RefCell<Node<T>>> {
Rc::new(RefCell::new(Node {
value: value,
next: None,
}))
}
}
///
/// A singly-linked list, with nodes allocated on the heap using `Rc`s and `RefCell`s. Here's an image illustrating a linked list:
///
///
/// ![](https://upload.wikimedia.org/wikipedia/commons/6/6d/Singly-linked-list.svg)
///
/// *Found on https://en.wikipedia.org/wiki/Linked_list*
///
/// # Usage
///
/// ```ignore
/// let list = List::new_empty();
/// ```
///
#[derive(Clone)]
pub struct List<T> where T: Sized + Clone {
head: Link<T>,
tail: Link<T>,
///
/// The length of the list.
///
pub length: usize,
}
impl<T> List<T> where T: Sized + Clone {
///
/// Creates a new empty list.
///
///
/// # Example
///
/// ```
/// # use mut_sharing_ownership::list::List;
/// let list: List<i32> = List::new_empty();
/// ```
///
pub fn new_empty() -> List<T> {
List { head: None, tail: None, length: 0 }
}
///
/// Appends a node to the list at the end.
///
///
/// # Panics
///
/// This never panics (probably).
///
/// # Safety
///
/// No unsafe code was used.
///
/// # Example
///
/// ```
/// use mut_sharing_ownership::list::List;
///
/// let mut list = List::new_empty();
/// list.append(10);
/// ```
///
pub fn append(&mut self, value: T) {
let new = Node::new(value);
match self.tail.take() {
Some(old) => old.borrow_mut().next = Some(new.clone()),
None => self.head = Some(new.clone())
};
self.length += 1;
self.tail = Some(new);
}
///
/// Removes the list's head and returns the result.
///
///
/// # Panics
///
/// Whenever when a node unexpectedly is `None`
///
/// # Example
///
/// ```
/// # use mut_sharing_ownership::list::List;
///
/// let mut list = List::new_empty();
/// list.append(10);
/// assert_eq!(list.pop(), Some(10));
/// ```
///
pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|head| {
if let Some(next) = head.borrow_mut().next.take() {
self.head = Some(next);
} else {
self.tail.take();
}
self.length -= 1;
Rc::try_unwrap(head)
.ok()
.expect("Something is terribly wrong")
.into_inner()
.value
})
}
///
/// Splits off and returns `n` nodes as a `List<T>`.
///
/// # Arguments
///
/// `n: usize` - The number of elements after which to split the list.
///
/// # Panics
///
/// Panics when:
/// - The list is empty
/// - `n` is larger than the length
///
/// # Example
///
/// ```
/// # use mut_sharing_ownership::list::List;
///
/// let mut list = List::new_empty();
/// list.append(12);
/// list.append(11);
/// list.append(10);
/// let mut list2 = list.split(1);
/// assert_eq!(list2.pop(), Some(12));
/// assert_eq!(list.pop(), Some(11));
/// assert_eq!(list.pop(), Some(10));
/// ```
///
pub fn split(&mut self, n: usize) -> List<T> {
// Don't do this in real life. Use Results, Options, or anything that
// doesn't just kill the program
if self.length == 0 || n >= self.length - 1 {
panic!("That's not working");
}
let mut n = n;
let mut new_list = List::new_empty();
while n > 0 {
new_list.append(self.pop().unwrap());
n -= 1;
}
new_list
}
}
impl <T>Drop for List<T> where T: Clone + Sized {
fn drop(&mut self) {
while self.length > 0 {
let n = self.pop();
drop(n);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_list_new_empty() {
let mut list: List<i32> = List::new_empty();
assert_eq!(list.length, 0);
assert_eq!(list.pop(), None);
}
#[test]
fn test_list_append() {
let mut list = List::new_empty();
list.append(1);
list.append(1);
list.append(1);
list.append(1);
list.append(1);
assert_eq!(list.length, 5);
}
#[test]
fn test_list_pop() {
let mut list = List::new_empty();
list.append(1);
list.append(1);
list.append(1);
list.append(1);
list.append(1);
assert_eq!(list.length, 5);
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), Some(1));
assert_eq!(list.length, 0);
assert_eq!(list.pop(), None);
}
#[test]
fn test_list_split() {
let mut list = List::new_empty();
list.append(1);
list.append(1);
list.append(1);
list.append(1);
list.append(1);
assert_eq!(list.length, 5);
let list2 = list.split(3);
assert_eq!(list.length, 2);
assert_eq!(list2.length, 3);
}
#[test]
#[should_panic]
fn test_list_split_panics() {
let mut list: List<i32> = List::new_empty();
let _ = list.split(3);
}
}

Wyświetl plik

@ -1,4 +1,3 @@
extern crate tch;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::path::Path; use std::path::Path;
use std::time::Instant; use std::time::Instant;
@ -118,14 +117,18 @@ fn predict_from_best() -> failure::Fallible<()> {
let net = ConvNet::new(&vs.root(), 10); let net = ConvNet::new(&vs.root(), 10);
// restore weights // restore weights
println!("Loading model weights from '{}'", model_weights_path.to_string_lossy()); println!(
"Loading model weights from '{}'",
model_weights_path.to_string_lossy()
);
vs.load(model_weights_path)?; vs.load(model_weights_path)?;
println!("Probabilities and predictions for 10 random images in the test set"); println!("Probabilities and predictions for 10 random images in the test set");
for (image_batch, label_batch) in m.test_iter(1).shuffle().to_device(vs.device()).take(10) { for (image_batch, label_batch) in m.test_iter(1).shuffle().to_device(vs.device()).take(10) {
let raw_tensor = net let raw_tensor = net
.forward_t(&image_batch, false) .forward_t(&image_batch, false)
.softmax(-1).view(m.labels); .softmax(-1)
.view(m.labels);
let predicted_index: Vec<i64> = raw_tensor.argmax(0, false).into(); let predicted_index: Vec<i64> = raw_tensor.argmax(0, false).into();
let probabilities: Vec<f64> = raw_tensor.into(); let probabilities: Vec<f64> = raw_tensor.into();