I am migrating a project from python to rust, more specifically right now a file which uses the pymemchace library to call the set and get methods.
In order to set and get the cache a class was created, something like this:
class Example:
def __init__(self):
# Create connection with to memcached server
def set_cache(self, ... ):
# Set cache
def get_cache(self, ... ):
# Get cache
Instance = Example()
I know the OOP concepts like classes are implemented a differently on Rust compared to python.
How do you guys think I should approach this ? Build a struct and implement a method using the memcache crate or build a trait and call it as I needed ?
Edit[7/11/2022]:
After reading the comments this is the first model I have for the implementation of the memecache main methods:
rust
extern crate memcache;
use memcache::{Client, MemcacheError};
pub struct CacheManager {
client: memcache::Client,
}
impl CacheManager {
pub fn __ini__() -> Self {
CacheManager {
client: memcache::Client::connect("memcache://localhost:11211").unwrap(),
}
}
pub fn set_cache(&self, key: &str, val: &str, expire: u32) -> bool {
self.client.set(key, val, expire).unwrap();
self.client.replace(" ", "", 100000000).unwrap();
true
}
pub fn get_cache(&self, key: &str) -> Result<Option<String>, MemcacheError> {
self.client.replace(" ", "", 100000000).unwrap();
self.client.get(key)
}
pub fn get_or_set(self, key: &str, val: &str) -> bool {
//If status cache already exist and value is the same then do nothing else set it
let cache_val = self.get_cache(key);
match cache_val.unwrap() {
Some(i) => {
if (i.parse::<i32>().unwrap() - val.parse::<i32>().unwrap()) < 1 {
true
} else {
false
}
}
None => {
self.set_cache(key, val, 86400);
false
}
}
}
}
What do you guys think ?
I will build some testing mod to try it out now.
Related
I have a rust struct that uses the pyo3 pyclass macro to allow using in python. This works fine for simple structs but if I have a struct that contains a type from a different library it becomes more difficult.
Example:
use geo::Point;
#[pyclass]
#[derive(Clone, Copy)]
pub struct CellState {
pub id: u32,
pub position: Point<f64>,
pub population: u32,
}
Above we use the Point type from the rust geo library. The compiler provides the following error:
the trait `pyo3::PyClass` is not implemented for `geo::Point<f64>
If I then try to implement PyClass on the Point:
impl PyClass for Point<f64> {}
It gives me the following compiler error:
impl doesn't use only types from inside the current crate
Any ideas on a clean and simple way to resolve this?
Until a better answer comes up my solution was to nest the class inside a python class but I then had to manually write the getters and setters.
#[pyclass]
#[derive(Clone)]
pub struct CellStatePy {
pub inner: CellState,
}
#[pymethods]
impl CellStatePy {
#[new]
pub fn new(id: u32, pos: (f64, f64), population: u32) -> Self {
CellStatePy {
inner: CellState {
id: CellIndex(id),
position: point!(x: pos.0, y: pos.1),
population,
},
}
}
}
Then implement PyObjectProtocol:
#[pyproto]
impl PyObjectProtocol for CellStatePy {
fn __str__(&self) -> PyResult<&'static str> {
Ok("CellStatePy")
}
fn __repr__<'a>(&'a self) -> PyResult<String> {
Ok(format!("CellStateObj id: {:?}", self.inner.id))
}
fn __getattr__(&'a self, name: &str) -> PyResult<String> {
let out: String = match name {
"id" => self.inner.id.into(),
"position" => format!("{},{}", self.inner.position.x(), self.inner.position.y()),
"population" => format!("{}", self.inner.population),
&_ => "INVALID FIELD".to_owned(),
};
Ok(out)
}
}
I'm quite new with Rust, and my first 'serious' project has involved writing a Python wrapper for a small Rust library using PyO3. This has mostly been quite painless, but I'm struggling to work out how to expose lazy iterators over Rust Vecs to Python code.
So far, I have been collecting the values produced by the iterator and returning a list, which obviously isn't the best solution. Here's some code which illustrates my problem:
use pyo3::prelude::*;
// The Rust Iterator, from the library I'm wrapping.
pub struct RustIterator<'a> {
position: usize,
view: &'a Vec<isize>
}
impl<'a> Iterator for RustIterator<'a> {
type Item = &'a isize;
fn next(&mut self) -> Option<Self::Item> {
let result = self.view.get(self.position);
if let Some(_) = result { self.position += 1 };
result
}
}
// The Rust struct, from the library I'm wrapping.
struct RustStruct {
v: Vec<isize>
}
impl RustStruct {
fn iter(&self) -> RustIterator {
RustIterator{ position: 0, view: &self.v }
}
}
// The Python wrapper class, which exposes the
// functions of RustStruct in a Python-friendly way.
#[pyclass]
struct PyClass {
rust_struct: RustStruct,
}
#[pymethods]
impl PyClass {
#[new]
fn new(v: Vec<isize>) -> Self {
let rust_struct = RustStruct { v };
Self{ rust_struct }
}
// This is what I'm doing so far, which works
// but doesn't iterate lazily.
fn iter(&self) -> Vec<isize> {
let mut output_v = Vec::new();
for item in self.rust_struct.iter() {
output_v.push(*item);
}
output_v
}
}
I've tried to wrap the RustIterator class with a Python wrapper, but I can't use PyO3's #[pyclass] proc. macro with lifetime parameters. I looked into pyo3::types::PyIterator but this looks like a way to access a Python iterator from Rust rather than the other way around.
How can I access a lazy iterator over RustStruct.v in Python? It's safe to assume that the type contained in the Vec always derives Copy and Clone, and answers which require some code on the Python end are okay (but less ideal).
You can make your RustIterator a pyclass and then implement the proper trait (PyIterProtocol) using the rust iter itself.
Not tested, but something like:
#[pyclass]
pub struct RustIterator<'a> {
position: usize,
view: &'a Vec<isize>
}
impl<'a> Iterator for RustIterator<'a> {
type Item = &'a isize;
fn next(&mut self) -> Option<Self::Item> {
let result = self.view.get(self.position);
if let Some(_) = result { self.position += 1 };
result
}
}
#[pyproto]
impl PyIterProtocol for Iter {
fn __next__(mut slf: PyRefMut<Self>) -> IterNextOutput<usize, &'static str> {
match self.next() {
Some(value) => IterNextOutput::Yield(value),
None => IterNextOutput::Return("Ended")
}
}
}
I have multiple Hazelcast sets for which I want to find the Intersection, however I want to avoid pulling any data on the client side. My current approach is exactly that with this code. It finds intersection between the 1st set and the list of the rest of set so that set1 is now the intersection of all.
for i in range(1, len(sets)):
cur = sets[i]
set1.retain_all(cur.get_all())
Hazelcast's retain_all doesn't work with 2 set entities, only with a set and a collection which is not what I am looking for. For example, it can be done with Redis with this code, so I want its Hazelcast equivalent.
set_result = "set_result"
redisClient.sinterstore(set_result, *list(sets))
Any help would be appreciated!
Since Hazelcast's ISet is a Set which is a Collection the following code should work:
set1.retainAll(cur);
But, it doesn't seem like you'd like set1 to be modified but would rather store the result in a different set much like redis' sinterstore function.
The following is an example of an alternative implementation:
public class RetainAllExample {
public static void main(String[] args) {
HazelcastInstance h1 = Hazelcast.newHazelcastInstance();
HazelcastInstance h2 = Hazelcast.newHazelcastInstance();
Set<String> set1 = h1.getSet("set1");
Set<String> set2 = h1.getSet("set2");
set1.add("a");
set1.add("b");
set1.add("c");
set1.add("d");
set2.add("c");
set2.add("d");
set2.add("e");
String resultName = "result";
String[] setNames = new String[] { "set1", "set2"};
RetainAll retainAll = new RetainAll(resultName, setNames;
IExecutorService exec = h1.getExecutorService("HZ-Executor-1");
Future<Boolean> task = exec.submit(retainAll);
try {
if(task.get(1_000, TimeUnit.MILLISECONDS)) {
Set<String> result = h1.getSet(resultName);
result.forEach(str -> System.out.println(str + ", "));
}
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
System.exit(0);
}
static class RetainAll implements Callable<Boolean>, HazelcastInstanceAware, Serializable {
private HazelcastInstance hazelcastInstance;
private String resultSetName;
private String[] setNames;
public RetainAll(String resultSetName, String[] setNames) {
this.resultSetName = resultSetName;
this.setNames = setNames;
}
#Override
public Boolean call() {
try {
Set[] sets = new Set[setNames.length];
IntStream.range(0, setNames.length).forEach(i -> sets[i] = hazelcastInstance.getSet(setNames[i]));
ISet resultSet = hazelcastInstance.getSet(resultSetName);
resultSet.addAll(sets[0]);
IntStream.range(1, sets.length).forEach(i -> resultSet.retainAll(sets[i]));
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
#Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.hazelcastInstance = hazelcastInstance;
}
}
}
I am studying design pattern which I can implement to achieve the same purpose as below. However, I am stuck since most of the examples in the net are pretty simple.
I have tried to look at factory method or even strategy method but can't figure out if any of them could be used.
Any suggestion from the guru here?
def checkSomething():
if ...:
return True
else:
return False
def main(mode, state):
if checkSomething() == False:
if mode == False or (mode == True and state == False):
obj_a = Class_A()
return obj_a
else:
Class_B().run()
obj_c = Class_C()
return obj_c
You can return a pair or tuple where first part may be some enum indicating type.
You can create a base class and derive your return class type from common base class. Here, you need to design your program to depend on base class rather than on derived type.
all my personally thoughts
factory pattern opted out here: you are not only creating objects but also making them do stuff
state machine opted out here: there is no state transition here
So I am using the strategy pattern below. But I think you can still use the factory pattern on top so that you further separate the concern of the creation of objects out from the strategy classes.
sort of C# pseudo code here:
interface IClass
{
void Run();
}
class Class_A : IClass { ... }
class Class_B : IClass { ... }
class Class_C : IClass { ... }
interface IStrategy
{
IClass Execute();
}
class StrategyA : IStrategy
{
IClass IStrategy.Execute()
{
var obj_a = Class_A();
return obj_a;
}
}
class StrategyB : IStrategy
{
IClass IStrategy.Execute()
{
Class_B.Run();
var obj_c = Class_C();
return obj_c;
}
}
class DecisionMaker
{
private IStrategy _strategy;
public DecideStrategy(IStrategy strategy) => _strategy = strategy;
public IClass ExecuteStrategy() => _strategy.Execute();
}
main()
{
var decisionMaker = new decisionMaker();
if conditionA
decisionMaker.DecideStrategy(new StrategyA());
else if conditionB
decisionMaker.DecideStrategy(new StrategyB());
return decisionMaker.ExecuteStrategy();
}
I'm currently learning method chaining. I've provided a working python example.
#!/bin/python3
import sys
class Generator(object):
def __init__(self):
return None
def echo(self, myStr):
sys.stdout.write(myStr)
return self
g = Generator()
g.echo("Hello, ").echo("World!\n")
But the Scala version doesn't seem to work, no text is being output.
#!/usr/bin/env scala
final class Printer() {
def echo(msg: String): this.type = {
println(msg)
this
}
}
class Driver {
def main(args: Array[String]) {
var pr = new Printer();
pr.echo("Hello, ").echo("World!")
}
}
Does anybody know why the scala version is not working and why?
You need to compile and call your scala bytecode aferwards. Also, you don't need to specify this.type if your Printer is final, e.g. if your driver.scala file contains:
final class Printer() {
def echo(msg: String) = {
println(msg)
this
}
}
object Driver {
def main(args: Array[String]) {
var pr = new Printer();
pr.echo("Hello, ").echo("World!")
}
}
Then just call:
scalac driver.scala
scala Driver
You should call the main method in your script.
new Driver().main(...) should solve your problem.
Besides, it is the norm to define a main method in an object.
So, instead of
class Driver {
def main(args: Array[String]) {
var pr = new Printer();
pr.echo("Hello, ").echo("World!")
}
}
new Driver().main(...)
I would recommend the following.
object Driver {
def main(args: Array[String]) {
var pr = new Printer();
pr.echo("Hello, ").echo("World!")
}
}
Driver.main(...)
Good luck!