Kotlin reduce has limitations? - list

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

Related

How to compose two calls to Regex::replace_all?

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)
}

Cast of the List<String> to List<T> in Kotlin

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.

Creating an `std::env::Args` iterator for testing

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 :)

What is concise way of deep-copying a 2D MutableList?

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
}
}

Swift: statically "append" to tuple type

I have a templated struct in a Swift library I am writing. This struct has two characteristics:
Every struct "wraps" or "represents" another arbitrary type. A Foo<T> wraps a T
These structs can be "combined" to form a third struct, whose represented type should be a "combination" (read: tuple) of the first two. In another worlds, if fooA: Foo<A> and fooB: Foo<B>, then fooA + fooB should be of type Foo<(A, B)>.
This works well enough when there are only two types to combine, but when you chain this combination operation you start getting nested tuples, which is not what I want. For example, in the following code:
let a = Foo<A>(/* initialize */)
let b = Foo<B>(/* initialize */)
let c = Foo<C>(/* initialize */)
let d = a + b // type is Foo<(A, B)>
let e = d + c // type is Foo<((A, B), C)>
d has type Foo<(A, B)>, which is what we want, but e has type Foo<((A, B), C)>, which is an extra level of unwanted nesting.
I need some way to express that the combination of a Foo<A> and a Foo<B> is not a Foo<(A, B)>, but rather a Foo<A + B>, where + is a hypothetical static operation which means "if the first type is a tuple type, append the second type onto it, yielding a new, non-nested tuple type. If it is not a tuple type, simply make the tuple type (A, B).
This feels like pushing to compiler to (beyond?) its limits, and I suspect that it might not be possible with Swift's current templating capabilities and type system. Still, if anyone can offer a workaround, a redesign that doesn't encounter this problem in the first place, or something conceptually similar but not identical to what I'm trying to do, it would be extremely helpful. As things stand, I'm at an impasse.
I think there is no generic way to do that.
Maybe, you can do something like this:
struct Foo<T> {
let v: T
init(_ v:T) { self.v = v }
}
func +<A,B>(lhs: Foo<(A)>, rhs:Foo<(B)>) -> Foo<(A,B)> { return Foo(lhs.v.0, rhs.v.0) }
func +<A,B,C>(lhs: Foo<(A,B)>, rhs: Foo<(C)>) -> Foo<(A,B,C)> { return Foo(lhs.v.0, lhs.v.1, rhs.v.0) }
func +<A,B,C>(lhs: Foo<(A)>, rhs: Foo<(B,C)>) -> Foo<(A,B,C)> { return Foo(lhs.v.0, rhs.v.0, rhs.v.1) }
func +<A,B,C,D>(lhs: Foo<(A,B,C)>, rhs: Foo<(D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, lhs.v.1, lhs.v.2, rhs.v.0) }
func +<A,B,C,D>(lhs: Foo<(A,B)>, rhs: Foo<(C,D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, lhs.v.1, rhs.v.0, rhs.v.1) }
func +<A,B,C,D>(lhs: Foo<(A)>, rhs: Foo<(B,C,D)>) -> Foo<(A,B,C,D)> { return Foo(lhs.v.0, rhs.v.0, rhs.v.1, rhs.v.2) }
// ... as many as you want ...
let f1 = Foo<(Int, UInt)>(1, 2) + Foo<String>("string") // -> as Foo<(Int, UInt, String)>