I need to create a generic method that splits a string and casts values
inline fun <reified T: Any> convertFromString(myString: String) : List<T>{
val castedList = ArrayList<T>()
for(item in myString.split(";")){
castedList.add(item as T)
}
return castedList
}
I call this method convertFromString<Int>("1;2;3;4;5;6") and expect to have output List<Int> but it fails during the cast item as T.
How can I cast all values to generic T?
I would rather suggest you to supply a transformation function, e.g.
inline fun <T: Any> convertFromString(myString: String, transformation: (String) -> T)
= myString.split(";")
.map(transformation)
.toList()
Note that you can't cast the String to anything else then String that is why item as T will not work. With the transformation function you ensure that it is transformed correctly (as long as you do not use item as T as the transformation ;-)).
Some sample usages/transformation functions could be:
val doubleList = convertFromString("123;123") { it.toDouble() }
val intList = convertFromString("123;123") { it.toInt() }
val objList = convertFromString("data=123;data=444") { yourParser.parse(it) }
Additionally with that approach you do not require the reified anymore. The inline however is still useful for any function containing a lambda function.
Related
Regex::replace_all has the signature fn (text: &str) -> Cow<str>. How would two calls to this be written, f(g(x)), giving the same signature?
Here's some code I'm trying to write. This has the two calls separated out into two functions, but I couldn't get it working in one function either. Here's my lib.rs in a fresh Cargo project:
#![allow(dead_code)]
/// Plaintext and HTML manipulation.
use lazy_static::lazy_static;
use regex::Regex;
use std::borrow::Cow;
lazy_static! {
static ref DOUBLE_QUOTED_TEXT: Regex = Regex::new(r#""(?P<content>[^"]+)""#).unwrap();
static ref SINGLE_QUOTE: Regex = Regex::new(r"'").unwrap();
}
fn add_typography(text: &str) -> Cow<str> {
add_double_quotes(&add_single_quotes(text)) // Error! "returns a value referencing data owned by the current function"
}
fn add_double_quotes(text: &str) -> Cow<str> {
DOUBLE_QUOTED_TEXT.replace_all(text, "“$content”")
}
fn add_single_quotes(text: &str) -> Cow<str> {
SINGLE_QUOTE.replace_all(text, "’")
}
#[cfg(test)]
mod tests {
use crate::{add_typography};
#[test]
fn converts_to_double_quotes() {
assert_eq!(add_typography(r#""Hello""#), "“Hello”");
}
#[test]
fn converts_a_single_quote() {
assert_eq!(add_typography("Today's Menu"), "Today’s Menu");
}
}
Here's the best I could come up with, but this will get ugly fast when composing three or four functions:
fn add_typography(input: &str) -> Cow<str> {
match add_single_quotes(input) {
Cow::Owned(output) => add_double_quotes(&output).into_owned().into(),
_ => add_double_quotes(input),
}
}
A Cow contains maybe-owned data.
We can infer from what the replace_all function does that it returns borrowed data only if substitutions did not happen, otherwise it has to return new, owned data.
The problem arises when the inner call makes a substitution but the outer one does not. In that case, the outer call will simply pass its input through as Cow::Borrowed, but it borrows from the Cow::Owned value returned by the inner call, whose data now belongs to a Cow temporary that is local to add_typography(). The function would therefore return a Cow::Borrowed, but would borrow from the temporary, and that's obviously not memory-safe.
Basically, this function will only ever return borrowed data when no substitutions were made by either call. What we need is a helper that can propagate owned-ness through the call layers whenever the returned Cow is itself owned.
We can construct a .map() extension method on top of Cow that does exactly this:
use std::borrow::{Borrow, Cow};
trait CowMapExt<'a, B>
where B: 'a + ToOwned + ?Sized
{
fn map<F>(self, f: F) -> Self
where F: for <'b> FnOnce(&'b B) -> Cow<'b, B>;
}
impl<'a, B> CowMapExt<'a, B> for Cow<'a, B>
where B: 'a + ToOwned + ?Sized
{
fn map<F>(self, f: F) -> Self
where F: for <'b> FnOnce(&'b B) -> Cow<'b, B>
{
match self {
Cow::Borrowed(v) => f(v),
Cow::Owned(v) => Cow::Owned(f(v.borrow()).into_owned()),
}
}
}
Now your call site can stay nice and clean:
fn add_typography(text: &str) -> Cow<str> {
add_single_quotes(text).map(add_double_quotes)
}
I currently have the following function:
fun createMask(mask : String){
val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
ssnField.hint = mask
}
To unit test this I want to wrap the untestable code within createMask into a closure. (The untestable code is the view layer logic that's difficult to instantiate and execute in a unit test.) Here is what I want to do in pseudo code:
createMask(closure, mask : String){
closure = mask // closure function returns pointer to property (depending on closure return type, might need to use setter: closure.set(mask))
}
With the above, the caller then does:
fun caller(){
createMask((){
val ssnField : mywidgets.SSNField = findViewById (R.id.editTextText)
return ssnField.hint
}, "xxx-xx-xxx")
}
How do do what is expressed in pseudo code work in kotlin?
You can return a reference of the property if you make createMask accept a parameter of type () -> KMutableProperty0<String>. Then you can call the set method:
fun createMask(mask : String, block: () -> KMutableProperty0<String>) {
block().set(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
ssnField::hint
}
Alternatively, use (String) -> Unit to represent "any function that takes a string", if you want to allow callers to pass any function that has the "form" of a setter.
fun createMask(mask : String, block: () -> (String) -> Unit) {
block()(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
ssnField::hint.setter
}
Note that this method involves reflection, which may not be desirable. Alternatively, you can accept a closure that takes the string to be set, and let the caller set it in the closure:
fun createMask(mask: String, block: (String) -> Unit) {
block(mask)
}
// caller
createMask("xxx-xx-xxx") {
val ssnField = ...
// note that rather than responsible for returning a property, the caller
// is responsible for setting "it" to the property
ssnField.hint = it
}
(I'm assuming createMask does more than just setting a property. Otherwise it is quite pointless...)
I would like to implement the same following code, using the reduce method. I know this is possible in other languages, but I don't know how to achieve it in Kotlin
class A
class B (val a: A?)
fun test(listOfBs: List<B>): List<A> {
return listOfBs.filter { it.a != null }.map { it.a!! }
// TODO return listOfBs.reduce { ??? }
}
Instead of calling filter and then map, you can use mapNotNull from the Kotlin Standard Library. This function combines the two and you can avoid the Hold My Beer operator (!!).
Example:
fun test(listOfBs: List<B>): List<A> =
listOfBs.mapNotNull { it.a }
reduce in Kotlin is not suitable for this. It is declared like this:
inline fun <S, T : S> Iterable<T>.reduce(
operation: (acc: S, T) -> S
): S
Notice how it can only return an S, which is a super type of the element type T. This means that you can't reduce a List<B> to a List<A>.
In "other languages", you can specify an "identity element" when reducing, and you probably also want to do that. In Kotlin, you can do that with fold:
fun test(listOfBs: List<B>): List<A> =
listOfBs.fold(emptyList()) { acc, b ->
if (b.a != null) {
acc + listOf(b.a) // this is very bad code, it creates a bunch of unnecessary lists
} else {
acc
}
}
But of course, "mapping only if not null" is a common enough thing to do that it is already built into the Kotlin Standard Library - mapNotNull:
fun test(listOfBs: List<B>): List<A> =
listOfBs.mapNotNull { it.a }
You can have a look at how reduce is implemented in the Kotlin standard library:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce.html
Is there a way in Rust to create a std::env::Args from a Vec<String> in order to use it in a #[test] function?
I wish to test a function that gets a std::env::Args as an argument, but I don't know how to create such an object with a list of arguments I supply for the test.
I wasn't able to figure this one out from the docs, the source nor from Google searches.
The fields of std::env::Args are not documented, and there doesn't appear to be a public function to create one with custom fields. So, you're outta luck there.
But since it's just "An iterator over the arguments of a process, yielding a String value for each argument" your functions can take a String iterator or Vec without any loss of functionality or type safety. Since it's just a list of Strings, it doesn't make much sense to arbitrarily limit your functions to strings which happen to come from the command line.
Looking through Rust's own tests, that's just what they do. There's a lot of let args: Vec<String> = env::args().collect();
There's even an example in rustbuild where they strip off the name of the program and just feed the list of arguments.
use std::env;
use bootstrap::{Config, Build};
fn main() {
let args = env::args().skip(1).collect::<Vec<_>>();
let config = Config::parse(&args);
Build::new(config).build();
}
And bootstrap::Config::parse() looks like so:
impl Config {
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
...
I'm not a Rust expert, but that seems to be how the Rust folks handle the problem.
#Schwern's answer is good and it led me to this simpler version. Since std::env::Args implements Iterator with Item = String you can do this:
use std::env;
fn parse<T>(args: T)
where
T: Iterator<Item = String>,
{
for arg in args {
// arg: String
print!("{}", arg);
}
}
fn main() {
parse(env::args());
}
To test, you provide parse with an iterator over String:
#[test]
fn test_parse() {
let args = ["arg1", "arg2"].iter().map(|s| s.to_string());
parse(args);
}
I've wrote a little macro to make this easier, based on #Rossman's answer (and therefore also based on #Schwern's answer; thanks go to both):
macro_rules! make_string_iter {
($($element: expr), *) => {
{
let mut v = Vec::new();
$( v.push(String::from($element)); )*
v.into_iter()
}
};
}
It can be used in that way:
macro_rules! make_string_iter {
($($element: expr), *) => {
{
let mut v = Vec::new();
$( v.push(String::from($element)); )*
v.into_iter()
}
};
}
// We're using this function to test our macro
fn print_args<T: Iterator<Item = String>>(args: T) {
for item in args {
println!("{}", item);
}
}
fn main() {
// Prints a, b and c
print_args(make_string_iter!("a", "b", "c"))
}
Or try it out on the Rust Playground.
I'm not (yet) an expert in rust, any suggestions are highly welcome :)
The element already implemented deep copying.
fun <T : DeepCopiable> f(a: MutableList<MutableList<T>>) {
val copied = a.map { it.map { it.deepCopy() }.toMutableList() }.toMutableList()
...
}
I am using this kind of code, but it seems verbose.
Due to restrictions in the type system, this problem cannot be generalized to a single functon without bypassing type safety (and due to JVM type erasure you definitely don't want to go that rabbit hole when generics are involved¹).
However, you can write a chain of extension functions implementing a deep-copy pattern, delegating to the previous function for every increase in dimension, in a type safe matter:
private typealias I<E> = Iterable<E>
private typealias Copy<E> = (E) -> E
private inline fun <T, R> I<T>.mapToMutable(transform: (T) -> R): I<R> = mapTo(mutableListOf(), transform)
fun <E> I<E>.deepCopy1(c: Copy<E>) = mapToMutable { c(it) }
fun <E> I<I<E>>.deepCopy2(c: Copy<E>) = mapToMutable { it.deepCopy1(c) }
fun <E> I<I<I<E>>>.deepCopy3(c: Copy<E>) = mapToMutable { it.deepCopy2(c) }
fun <E> I<I<I<I<E>>>>.deepCopy4(c: Copy<E>) = mapToMutable { it.deepCopy3(c) }
fun <E> I<I<I<I<I<E>>>>>.deepCopy5(c: Copy<E>) = mapToMutable { it.deepCopy4(c) }
Due to JVM type erasure, the functions need different names (#JVMName does not help due to type interference ambiguity²). Type aliases are used to prevent horizontal space explosion³, and the function set is uncoupled from the deep-copiable interface via a generic copy function parameter.
Example usage:
fun main(args: Array<String>) {
data class IntHolder(var value: Int)
val original = List(3) { a ->
List(3) { b ->
IntHolder(a + b)
}
}
val copied = original.deepCopy2 { it.copy() }
original[0][0].value = 18258125
println("original=$original")
println("copied =$copied")
}
->
original=[[IntHolder(value=18258125), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]
copied =[[IntHolder(value=0), IntHolder(value=1), IntHolder(value=2)], [IntHolder(value=1), IntHolder(value=2), IntHolder(value=3)], [IntHolder(value=2), IntHolder(value=3), IntHolder(value=4)]]
[1]: Because generic type casts are performed by the compiler at runtime, a cast from List<Foo> to List<Baz> will always succeed at runtime, but fail later upon access of the casted list. Implementing mentioned magic "single function" is possible, but the slightest of error would result in a returned data structure that fails seemingly "random" upon access with class cast exceptions.
[2]: A value of type Iterable<Iterable<Foo>> satisfies both
fun <T> Iterable<T>.baz() (T = Iterable<Foo>) and
fun <T> Iterable<Iterable<T>.baz() (T = Foo)
Due to this, the compiler would not be able to determine the right method to use if all methods in the chain have the same function name, but different JVM names.
[3]:
Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<Iterable<ithinkyougetthepoint>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Here is a simple deep copy example by using java.lang.reflect.Array & java.lang.Cloneable.
Noet: the clone method performs a shallow copy of this object, not a deep copy operation, but you can override the clone method to provide a deep copy operation, for example:
val list = mutableListOf(mutableListOf(arrayOf(1)))
val copied = list.deepCopy()
println(copied !== list) //true: not the same
println(copied.map{it.map{it.toList()}} == list.map{it.map{it.toList()}})
// ^---true: content equals
// v--- Array is cloned, since it has implemented Cloneable
println(copied[0][0] !== array[0][0]) // true
typealias NativeArray = java.lang.reflect.Array
#Suppress("UNCHECKED_CAST")
fun <T> T.deepCopy(): T {
return when (this) {
is Array<*> -> {
val type = this.javaClass.componentType
NativeArray.newInstance(type, size).also {
this.forEachIndexed { i, item ->
NativeArray.set(it, i, item.deepCopy())
}
} as T
}
is MutableList<*> -> this.mapTo(mutableListOf()) { it.deepCopy() } as T
is List<*> -> this.map { it.deepCopy() } as T
is Cloneable -> this.javaClass.getDeclaredMethod("clone").let {
it.isAccessible = true;
it.invoke(this) as T
}
else -> this
}
}