Non-destructively iterating over a Rust collection, but not by reference - iterator

I can write the following two ways, the second is inspired by What is the idiomatic way to create a collection of references to methods that take self?:
channels.iter().flat_map(|c|c.to_uppercase()).collect(),
channels.clone().into_iter().flat_map(char::to_uppercase).collect(),
The second line has to clone the collection because char::to_uppercase doesn't accept a reference as it's argument and .iter() provides references and .into_iter() moves the collection.
Is there a way to do this that doesn't need to clone the collection or create a closure? I don't hate closures, I promise, and I know they're just turned into (usually inline) function calls in LLVM anyway, but I like the cleanness of referring to a function like in the second line and would prefer to use it if it can be done without the clone.

Iterator has a cloned method which is equivalent to .map(|x| x.clone()) which, in case of Copy types is equivalent to .map(|&x| x). This way you can write
channels.iter().cloned().flat_map(char::to_uppercase).collect()

You can define a function that takes a reference. You can even put it inside another function, if you want to keep it close to its usage.
fn foobar() {
fn to_uppercase(c: &char) -> ::std::char::ToUppercase {
c.to_uppercase()
}
// [...]
let channels_upper = channels.iter().flat_map(to_uppercase).collect();
}

Related

How can one invoke the non-extension `run` function (the one without scope / "object reference") in environments where there is an object scope?

Example:
data class T(val flag: Boolean) {
constructor(n: Int) : this(run {
// Some computation here...
<Boolean result>
})
}
In this example, the custom constructor needs to run some computation in order to determine which value to pass to the primary constructor, but the compiler does not accept the run, citing Cannot access 'run' before superclass constructor has been called, which, if I understand correctly, means instead of interpreting it as the non-extension run (the variant with no object reference in https://kotlinlang.org/docs/reference/scope-functions.html#function-selection), it construes it as a call to this.run (the variant with an object reference in the above table) - which is invalid as the object has not completely instantiated yet.
What can I do in order to let the compiler know I mean the run function which is not an extension method and doesn't take a scope?
Clarification: I am interested in an answer to the question as asked, not in a workaround.
I can think of several workarounds - ways to rewrite this code in a way that works as intended without calling run: extracting the code to a function; rewriting it as a (possibly highly nested) let expression; removing the run and invoking the lambda (with () after it) instead (funnily enough, IntelliJ IDEA tags that as Redundant lambda creation and suggests to Inline the body, which reinstates the non-compiling run). But the question is not how to rewrite this without using run - it's how to make run work in this context.
A good answer should do one of the following things:
Explain how to instruct the compiler to call a function rather than an extension method when a name is overloaded, in general; or
Explain how to do that specifically for run; or
Explain that (and ideally also why) it is not possible to do (ideally with supporting references); or
Explain what I got wrong, in case I got something wrong and the whole question is irrelevant (e.g. if my analysis is incorrect, and the problem is something other than the compiler construing the call to run as this.run).
If someone has a neat workaround not mentioned above they're welcome to post it in a comment - not as an answer.
In case it matters: I'm using multi-platform Kotlin 1.4.20.
Kotlin favors the receiver overload if it is in scope. The solution is to use the fully qualified name of the non-receiver function:
kotlin.run { //...
The specification is explained here.
Another option when the overloads are not in the same package is to use import renaming, but that won't work in this case since both run functions are in the same package.

Inherit from table returned from function

There is an API provided function, let's call it createBase which returns a table (object). I want to add methods to this table, but I can't just do x = createBase() and then function x:foo() because I have another function similar to createBase, but it's createExtended. It might be easier to explain with the code I have so far:
import api --I don't know how you'd do this in vanilla Lua, I'd use os.loadAPI("api") but that's computercraft specific, I think
Extended = {}
function Extended:foo()
print("foo from extended")
end
function createExtended(params)
x = api.createBase(params)
Extended.__index = x
return Extended --this is obviously wrong: you can't return a class and expect it to be an object
end
Of course, this doesn't work: but I don't know how I might make it work either. Let's assume the table returned by createBase has a function called bar which just prints bar from base. With this test code, the following outputs are given:
e = createExtended()
e.foo() --prints "foo from extended"
e.bar() --nil, therefor error
How can I make this possible, short of defining function x.bar() inside createExtended?
Thanks in advance.
The very simplest way is to attach the method to it directly, instead of using a metatable.
local function extend(super_instance)
super_instance.newMethod = newMethod
return super_instance
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work, unless your superclass uses __newindex (for example, preventing you from writing to unknown properties/methods), or iterates over the keys using pairs or next, since it will now have an additional key.
If for some reason you cannot modify the object, you will instead have to 'wrap' it up.
You could make a new instance which "proxies" all of its methods, properties, and operators to another instance, except that it adds additional fields and methods.
local function extend(super_instance)
local extended_instance = {newMethod = newMethod}
-- and also `__add`, `__mul`, etc as needed
return setmetatable(extended_instance, {__index = super_instance, __newindex = super_instance})
end
local function createExtended(...)
return extend(createSuper(...))
end
This will work for simple classes, but won't work for all uses:
Table iteration like pairs and next won't find the keys from the original table, since they're not actually there. If the superclass inspects the metatable of the object it is given (or if the superclass is actually a userdata), it will also not work, since you'll find the extension metatable instead.
However, many pure-Lua classes will not do those things, so this is still a fairly simple approach that will probably work for you.
You could also do something similar to Go; instead of having a way to 'extend' a class, you simply embed that class as a field and offer convenience to directly calling methods on the wrapping class that just call the methods on the 'extended' class.
This is slightly complicated by how 'methods' work in Lua. You can't tell if a property is a function-that-is-a-property or if it's actually a method. The code below assumes that all of the properties with type(v) == "function" are actually methods, which will usually be true, but may not actually be for your specific case.
In the worst case, you could just manually maintain the list of methods/properties you want to 'proxy', but depending on how many classes you need to proxy and how many properties they have, that could become unwieldy.
local function extend(super_instance)
return setmetatable({
newMethod = newMethod, -- also could be provided via a more complicated __index
}, {
__index = function(self, k)
-- Proxy everything but `newMethod` to `super_instance`.
local super_field = super_instance[k]
if type(super_field) == "function" then
-- Assume the access is for getting a method, since it's a function.
return function(self2, ...)
assert(self == self2) -- assume it's being called like a method
return super_field(super_instance, ...)
end
end
return super_field
end,
-- similar __newindex and __add, etc. if necessary
})
end
local function createExtended(...)
return extend(createSuper(...))
end

Mixing-in roles in traits apparently not working

This example is taken from roast, although it's been there for 8 years:
role doc { has $.doc is rw }
multi trait_mod:<is>(Variable $a, :$docced!) {
$a does doc.new(doc => $docced);
}
my $dog is docced('barks');
say $dog.VAR;
This returns Any, without any kind of role mixed in. There's apparently no way to get to the "doc" part, although the trait does not error. Any idea?
(This answer builds on #guifa's answer and JJ's comment.)
The idiom to use in variable traits is essentially $var.var.VAR.
While that sounds fun when said aloud it also seems crazy. It isn't, but it demands explanation at the very least and perhaps some sort of cognitive/syntactic relief.
Here's the brief version of how to make some sense of it:
$var makes sense as the name of the trait parameter because it's bound to a Variable, a compiler's-eye view of a variable.
.var is needed to access the user's-eye view of a variable given the compiler's-eye view.
If the variable is a Scalar then a .VAR is needed as well to get the variable rather than the value it contains. (It does no harm if it isn't a Scalar.)
Some relief?
I'll explain the above in more detail in a mo, but first, what about some relief?
Perhaps we could introduce a new Variable method that does .var.VAR. But imo this would be a mistake unless the name for the method is so good it essentially eliminates the need for the $var.var.VAR incantation explanation that follows in the next section of this answer.
But I doubt such a name exists. Every name I've come up with makes matters worse in some way. And even if we came up with the perfect name, it would still barely be worth it at best.
I was struck by the complexity of your original example. There's an is trait that calls a does trait. So perhaps there's call for a routine that abstracts both that complexity and the $var.var.VAR. But there are existing ways to reduce that double trait complexity anyway, eg:
role doc[$doc] { has $.doc is rw = $doc}
my $dog does doc['barks'];
say $dog.doc; # barks
A longer explanation of $var.var.VAR
But $v is already a variable. Why so many var and VARs?
Indeed. $v is bound to an instance of the Variable class. Isn't that enough?
No, because a Variable:
Is for storing metadata about a variable while it's being compiled. (Perhaps it should have been called Metadata-About-A-Variable-Being-Compiled? Just kidding. Variable looks nice in trait signatures and changing its name wouldn't stop us needing to use and explain the $var.var.VAR idiom anyway.)
Is not the droid we are looking for. We want a user's-eye view of the variable. One that's been declared and compiled and is then being used as part of user code. (For example, $dog in the line say $dog.... Even if it were BEGIN say $dog..., so it ran at compile-time, $dog would still refer to a symbol that's bound to a user's-eye view container or value. It would not refer to the Variable instance that's only the compiler's-eye view of data related to the variable.)
Makes life easier for the compiler and those writing traits. But it requires that a trait writer accesses the user's-eye view of the variable to access or alter the user's-eye view. The .var attribute of the Variable stores that user's-eye view. (I note the roast test has a .container attribute that you omitted. That's clearly now been renamed .var. My guess is that that's because a variable may be bound to an immutable value rather than a container so the name .container was considered misleading.)
So, how do we arrive at $var.var.VAR?
Let's start with a variant of your original code and then move forward. I'll switch from $dog to #dog and drop the .VAR from the say line:
multi trait_mod:<is>(Variable $a, :$docced!) {
$a does role { has $.doc = $docced }
}
my #dog is docced('barks');
say #dog.doc; # No such method 'doc' for invocant of type 'Array'
This almost works. One tiny change and it works:
multi trait_mod:<is>(Variable $a, :$docced!) {
$a.var does role { has $.doc = $docced }
}
my #dog is docced('barks');
say #dog.doc; # barks
All I've done is add a .var to the ... does role ... line. In your original, that line is modifying the compiler's-eye view of the variable, i.e. the Variable object bound to $a. It doesn't modify the user's-eye view of the variable, i.e. the Array bound to #dog.
As far as I know everything now works correctly for plural containers like arrays and hashes:
#dog[1] = 42;
say #dog; # [(Any) 42]
say #dog.doc; # barks
But when we try it with a Scalar variable:
my $dog is docced('barks');
we get:
Cannot use 'does' operator on a type object Any.
This is because the .var returns whatever it is that the user's-eye view variable usually returns. With an Array you get the Array. But with a Scalar you get the value the Scalar contains. (This is a fundamental aspect of P6. It works great but you have to know it in these sorts of scenarios.)
So to get this to appear to work again we have to add a couple .VAR's as well. For anything other than a Scalar a .VAR is a "no op" so it does no harm to cases other than a Scalar to add it:
multi trait_mod:<is>(Variable $a, :$docced!) {
$a.var.VAR does role { has $.doc = $docced }
}
And now the Scalar case also appears to work:
my $dog is docced('barks');
say $dog.VAR.doc; # barks
(I've had to reintroduce the .VAR in the say line for the same reason I had to add it to the $a.var.VAR ... line.)
If all were well that would be the end of this answer.
A bug
But something is broken. If we'd attempted to initialize the Scalar variable:
my $dog is docced('barks') = 42;
we'd see:
Cannot assign to an immutable value
As #guifa noted, and I stumbled on a while back:
It seems that a Scalar with a mixin no longer successfully functions as a container and the assignment fails. This currently looks to me like a bug.
Not a satisfactory answer but maybe you can progress from it
role doc {
has $.doc is rw;
}
multi trait_mod:<is>(Variable:D $v, :$docced!) {
$v.var.VAR does doc;
$v.var.VAR.doc = $docced;
}
say $dog; # ↪︎ Scalar+{doc}.new(doc => "barks")
say $dog.doc;  # ↪︎ barks
$dog.doc = 'woofs'; #
say $dog; # ↪︎ Scalar+{doc}.new(doc => "woofs")
Unfortunately, there is something off with this, and applying the trait seems to cause the variable to become immutable.

How to make and use an arraylist of functions

How can i make an arraylist of functions, and call each function easily? I have already tried making an ArrayList<Function<Unit>>, but when i tried to do this:
functionList.forEach { it }
and this:
for(i in 0 until functionList.size) functionList[i]
When i tried doing this: it() and this: functionList[i](), but it wouldn't even compile in intellij. How can i do this in kotlin? Also, does the "Unit" in ArrayList<Function<Unit>> mean return value or parameters?
Just like this:
val funs:List<() -> Unit> = listOf({}, { println("fun")})
funs.forEach { it() }
The compiler can successfully infer the type of funs here which is List<() -> Unit>. Note that () -> Unit is a function type in Kotlin which represents a function that does not take any argument and returns Unit.
I think there are two problems with the use of the Function interface here.
The first problem is that it doesn't mean what you might think. As I understand it, it's a very general interface, implemented by all functions, however many parameters they take (or none). So it doesn't have any invoke() method. That's what the compiler is complaining about.
Function has several sub-interfaces, one for each 'arity' (i.e. one for each number of parameters): Function0 for functions that take no parameters, Function1 for functions taking one parameter, and so on. These have the appropriate invoke() methods. So you could probably fix this by replacing Function by Function0.
But that leads me on to the second problem, which is that the Function interfaces aren't supposed to be used this way. I think they're mainly for Java compatibility and/or for internal use by the compiler.
It's usually much better to use the Kotlin syntax for function types: (P1, P2...) -> R. This is much easier to read, and avoids these sorts of problems.
So the real answer is probably to replace Function<Unit> by () -> Unit.
Also, in case it's not clear, Kotlin doesn't have a void type. Instead, it has a type called Unit, which has exactly one value. This might seem strange, but makes better sense in the type system, as it lets the compiler distinguish functions that return without an explicit value, from those which don't return. (The latter might always throw an exception or exit the process. They can be defined to return Nothing -- a type with no values at all.)

How to mutate another item in a vector, but not the vector itself, while iterating over the vector?

It is quite clear to me that iterating over a vector shouldn't let the loop body mutate the vector arbitrarily. This prevents iterator invalidation, which is prone to bugs.
However, not all kinds of mutation lead to iterator invalidation. See the following example:
let mut my_vec: Vec<Vec<i32>> = vec![vec![1,2], vec![3,4], vec![5,6]];
for inner in my_vec.iter_mut() { // <- or .iter()
// ...
my_vec[some_index].push(inner[0]); // <-- ERROR
}
Such a mutation does not invalidate the iterator of my_vec, however it is disallowed. It could invalidate any references to the specific elements in my_vec[some_index] but we do not use any such references anyway.
I know that these questions are common, and I'm not asking for an explanation. I am looking for a way to refactor this so that I can get rid of this loop. In my actual code I have a huge loop body and I can't modularize it unless I express this bit nicely.
What I have thought of so far:
Wrapping the vector with Rc<RefCell<...>>. I think this would still fail at runtime, since the RefCell would be borrowed by the iterator and then will fail when the loop body tries to borrow it.
Using a temporary vector to accumulate the future pushes, and push them after the loop ends. This is okay, but needs more allocations than pushing them on the fly.
Unsafe code, and messing with pointers.
Anything listed in the Iterator documentation does not help. I checked out itertools and it looks like it wouldn't help either.
Using a while loop and indexing instead of using an iterator making use of a reference to the outer vector. This is okay, but does not let me use iterators and adapters. I just want to get rid of this outer loop and use my_vec.foreach(...).
Are there any idioms or any libraries which would let me do this nicely Unsafe functions would be okay as long as they don't expose pointers to me.
You can wrap each of the inner vectors in a RefCell.
use std::cell::RefCell;
fn main() {
let my_vec : Vec<RefCell<Vec<i32>>> = vec![
RefCell::new(vec![1,2]),
RefCell::new(vec![3,4]),
RefCell::new(vec![5,6])];
for inner in my_vec.iter() {
// ...
let value = inner.borrow()[0];
my_vec[some_index].borrow_mut().push(value);
}
}
Note that the value binding here is important if you need to be able to push to the vector that inner refers to. value happens to be a type that doesn't contain references (it's i32), so it doesn't keep the first borrow active (it ends by the end of the statement). Then, the next statement may borrow the same vector or another vector mutably and it'll work.
If we wrote my_vec[some_index].borrow_mut().push(inner.borrow()[0]); instead, then both borrows would be active until the end of the statement. If both my_vec[some_index] and inner refer to the same RefCell<Vec<i32>>, this will panic with RefCell<T> already mutably borrowed.
Without changing the type of my_vec, you could simply use access by indexing and split_at_mut:
for index in 0..my_vec.len() {
let (first, second) = my_vec.split_at_mut(index);
first[some_index].push(second[0]);
}
Note: beware, the indices in second are off by index.
This is safe, relatively easy, and very flexible. It does not, however, work with iterator adaptors.