Consider the following code, where we take chunks of a list, join them and print to stdout:
val l = listOf("1", "2", "3", "4", "5", "6", "7")
l.chunked(3, { a -> a.joinToString()}).forEach(::println)
The code works without a problem. I wanted to change the lambda call ({ a -> a.joinToString()}) to the method reference, like this:
l.chunked(3, l::joinToString).forEach(::println)
The code that uses method reference does not compile and the errors given are:
Error:(4, 7) Kotlin: Type inference failed: fun
Iterable.chunked(size: Int, transform: (List) -> R): List
cannot be applied to receiver: List arguments:
(Int,KFunction6<#ParameterName CharSequence, #ParameterName
CharSequence, #ParameterName CharSequence, #ParameterName Int,
#ParameterName CharSequence, #ParameterName(name = "transform")
((String) -> CharSequence)?, String>)
Error:(4, 18) Kotlin: Type mismatch: inferred type is
KFunction6<#ParameterName CharSequence, #ParameterName CharSequence,
#ParameterName CharSequence, #ParameterName Int, #ParameterName
CharSequence, #ParameterName(name = "transform") ((String) ->
CharSequence)?, String> but (List) -> ??? was expected
Error:(4, 21) Kotlin: Type inference failed: fun
Iterable.joinToString(separator: CharSequence = ..., prefix:
CharSequence = ..., postfix: CharSequence = ..., limit: Int = ...,
truncated: CharSequence = ..., transform: ((T) -> CharSequence)? =
...): String cannot be applied to receiver: List arguments:
()
Is there a way to compile the code with method references instead of lambda call? I am beginning to learn Kotlin, but suppose that the errors stem from the fact that joinToString uses a number of default arguments?
There's an open feature request in the Kotlin issue tracker with the title "Support function references with default values as other function types", which seems to be what's missing for your use-case to work.
The feature currently has a target version of 1.3.
Update
The 1.3 Kotlin release does not contain this feature, the target version is updated to 1.4
Related
I am creating bindings in Rust for a C library and Bindgen generated enums like:
// Rust
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rmw_qos_history_policy_t {
RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT = 0,
RMW_QOS_POLICY_HISTORY_KEEP_LAST = 1,
RMW_QOS_POLICY_HISTORY_KEEP_ALL = 2,
RMW_QOS_POLICY_HISTORY_UNKNOWN = 3,
}
I need to convert these to:
// Rust
pub enum QoSHistoryPolicy {
SystemDefault = 0,
KeepLast = 1,
KeepAll = 2,
Unknown = 3,
}
When importing constant values from this C library:
// C library
const rmw_qos_history_policy_t some_value_from_C = RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT;
I would like to do something like:
let some_value: QoSHistoryPolicy = some_value_from_C;
How can I go about it?
The compiler does not inspect enums for ABI compatibility, and as such does not provide a direct way to convert values between these types. A few possible solutions follow.
1. One-by-one matching
This is trivial and safe, albeit leading to exhaustive code.
impl From<rmw_qos_history_policy_t> for QoSHistoryPolicy {
fn from(x: rmw_qos_history_policy_t) -> Self {
use rmw_qos_history_policy_t::*;
match x {
RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT => QoSHistoryPolicy::SystemDefault,
RMW_QOS_POLICY_HISTORY_KEEP_LAST => QoSHistoryPolicy::KeepLast,
RMW_QOS_POLICY_HISTORY_KEEP_ALL => QoSHistoryPolicy::KeepAll,
RMW_QOS_POLICY_HISTORY_UNKNOWN => QoSHistoryPolicy::Unknown,
}
}
}
2. Casting + FromPrimitive
Rust allows you to convert field-less enums into an integer type using the as operator. The opposite conversion is not always safe however. Derive FromPrimitive using the num crate to obtain the missing piece.
#[derive(FromPrimitive)]
pub enum QoSHistoryPolicy { ... }
impl From<rmw_qos_history_policy_t> for QoSHistoryPolicy {
fn from(x: rmw_qos_history_policy_t) -> Self {
FromPrimitive::from_u32(x as _).expect("1:1 enum variant matching, all good")
}
}
3. Need an enum?
In the event that you just want an abstraction to low-level bindings, you might go without a new enum type.
#[repr(transparent)]
pub struct QoSHistoryPolicy(rmw_qos_history_policy_t);
The type above contains the same information and binary representation, but can expose an encapsulated API. The conversion from the low-level type to the high-level type becomes trivial. The main downside is that you lose pattern matching over its variants.
4. You're on your own
When absolutely sure that the two enums are equivalent in their binary representation, you can transmute between them. The compiler won't help you here, this is far from recommended.
unsafe {
let policy: QoSHistoryPolicy = std::mem::transmute(val);
}
See also:
How do I match enum values with an integer?
It looks to be a good candidate for the From trait on QoSHistoryPolicy.
impl From<rmw_qos_history_policy_t> for QoSHistoryPolicy {
fn from(raw: rmw_qos_history_policy_t) -> Self {
match raw {
rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT => QoSHistoryPolicy::SystemDefault,
rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_LAST => QoSHistoryPolicy::KeepLast,
rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_KEEP_ALL => QoSHistoryPolicy::KeepAll,
rmw_qos_history_policy_t::RMW_QOS_POLICY_HISTORY_UNKNOWN => QoSHistoryPolicy::Unknown
}
}
}
so this should now work
let some_value: QoSHistoryPolicy = some_value_from_C.into();
I am trying to fast forward time to do some tests for a custom runtime module. I have looked at the answer from this thread and followed the answer to use Timestamp, however, I am unable to access the set_timestamp method.
setup:
#[cfg(test)]
mod tests {
use super::*;
use support::dispatch::Vec;
use runtime_primitives::traits::{Hash};
use runtime_io::with_externalities;
use primitives::{H256, Blake2Hasher};
use timestamp;
use support::{impl_outer_origin, assert_ok, assert_noop};
use runtime_primitives::{
BuildStorage,
traits::{BlakeTwo256, IdentityLookup},
testing::{Digest, DigestItem, Header}
};
impl_outer_origin! {
pub enum Origin for Test {}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Test;
impl system::Trait for Test {
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type Digest = Digest;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type Log = DigestItem;
}
impl super::Trait for Test {
type Event = ();
}
impl timestamp::Trait for Test {
type Moment = u64;
type OnTimestampSet = ();
}
type Pizza = Module<Test>;
And the error is below:
error[E0599]: no function or associated item named `set_timestamp` found for type
`srml_timestamp::Module<tests::Test>` in the current scope
|
254 | let now = <timestamp::Module<tests::Test>>::set_timestamp(9);
| ^^^^^^^^^^^^^ function or associated item
not found in `srml_timestamp::Module<tests::Test>`
In Substrate v1.0, the set_timestamp function has a #[cfg(feature = "std")] attribute on it:
https://github.com/paritytech/substrate/blob/v1.0/srml/timestamp/src/lib.rs#L276
This means it will only be visible if you are compiling with std. When you write tests, this should work, but I assume that this issue is appearing because you are trying to call it from within the runtime environment, which much be no_std.
If for some reason you do need to modify the timestamp from within your runtime, you should be able to do so directly:
https://github.com/paritytech/substrate/blob/v1.0/srml/timestamp/src/lib.rs#L249
<timestamp::Module<T>>::Now::put(new_time)
(I haven't tested this, but something like it should work).
Let me know if this helps.
In Substrate v1.0 you can declare
type Moment = timestamp::Module<Test>;
Then use it to set a specific timestamp.
Moment::set_timestamp(9);
If you want to get the timestamp value, you can do:
let now_timestamp = Moment::now();
I am trying to build a unit test like so:
// region is a (Double, Double) tuple
XCTAssertEqual(region, (0.0, 200.0))
But Xcode is giving me an error: Cannot invoke 'XCTAssertEqual' with an argument list of type ((Double, Double), (Double, Double))
Is there a different way to test tuples without extracting their members and testing individually?
XCTAssertEqual requires that the two parameters passed to it are Equatable, which you can see from the method signature. Note that expression1 returns T?, and T must be Equatable:
func XCTAssertEqual<T : Equatable>(_ expression1: #autoclosure () throws -> T?, _ expression2: #autoclosure () throws -> T?, _ message: #autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)
But Swift tuples aren't Equatable, so you can't use them with XCTAssertEqual.
Tuples do have an == method — they just don't conform to the protocol — so you could do something like this:
let eql = region == (0.0, 200.0)
XCTAssertTrue(eql)
Or even:
XCTAssertTrue(region == (0.0, 200.0))
Edit: I've expanded on this answer in a blog post, How to Make Specialized Test Assertions in Swift
A disadvantage of using
XCTAssertTrue(region == (0.0, 200.0))
is the inadequate reporting it gives upon failure:
XCTAssertTrue failed -
Now you have to track down what the actual values are, to understand what went wrong.
But you can add diagnostic information to the assertion like this:
XCTAssertTrue(region == (0.0, 200.0), "was \(region)")
For example:
XCTAssertTrue failed - was (1.0, 2.0)
If you plan to have several tests that compare this tuple, I wouldn't want to have to repeat this everywhere. Instead, create a custom assertion:
private func assertRegionsEqual(actual: (_: Double, _: Double), expected: (_: Double, _: Double), file: StaticString = #file, line: UInt = #line) {
if actual != expected {
XCTFail("Expected \(expected) but was \(actual)", file: file, line: line)
}
}
Now the test assertion is
assertRegionsEqual(actual: region, expected: (0.0, 200.0))
Upon failure, this yields a message like
failed - Expected (0.0, 200.0) but was (1.0, 2.0)
While learning Scalaz 6, I'm trying to write type-safe readers returning validations. Here are my new types:
type ValidReader[S,X] = (S) => Validation[NonEmptyList[String],X]
type MapReader[X] = ValidReader[Map[String,String],X]
and I have two functions creating map-readers for ints and strings (*):
def readInt( k: String ): MapReader[Int] = ...
def readString( k: String ): MapReader[String] = ...
Given the following map:
val data = Map( "name" -> "Paul", "age" -> "8" )
I can write two readers to retrieve the name and age:
val name = readString( "name" )
val age = readInt( "age" )
println( name(data) ) //=> Success("Paul")
println( age(data) ) //=> Success(8)
Everything works fine, but now I want to compose both readers to build a Boy instance:
case class Boy( name: String, age: Int )
My best take is:
val boy = ( name |#| age ) {
(n,a) => ( n |#| a ) { Boy(_,_) }
}
println( boy(data) ) //=> Success(Boy(Paul,8))
It works as expected, but the expression is awkward with two levels of applicative builders. Is there a way, to get the following syntax to work ?
val boy = ( name |#| age ) { Boy(_,_) }
(*) Full and runnable implementation in: https://gist.github.com/1891147
Update: Here is the compiler error message that I get when trying the line above or Daniel suggestion:
[error] ***/MapReader.scala:114: type mismatch;
[error] found : scalaz.Validation[scalaz.NonEmptyList[String],String]
[error] required: String
[error] val boy = ( name |#| age ) { Boy(_,_) }
[error] ^
How about this?
val boy = (name |#| age) {
(Boy.apply _).lift[({type V[X]=ValidationNEL[String,X]})#V]
}
or using a type alias:
type VNELStr[X] = ValidationNEL[String,X]
val boy = (name |#| age) apply (Boy(_, _)).lift[VNELStr]
This is based on the following error message at the console:
scala> name |#| age apply Boy.apply
<console>:22: error: type mismatch;
found : (String, Int) => MapReader.Boy
required: (scalaz.Validation[scalaz.NonEmptyList[String],String],
scalaz.Validation[scalaz.NonEmptyList[String],Int]) => ?
So I just lifted Boy.apply to take the required type.
Note that since Reader and Validation (with a semigroup E) are both Applicative, their composition is also Applicative. Using scalaz 7 this can be expressed as:
import scalaz.Reader
import scalaz.Reader.{apply => toReader}
import scalaz.{Validation, ValidationNEL, Applicative, Kleisli, NonEmptyList}
//type IntReader[A] = Reader[Int, A] // has some ambigous implicit resolution problem
type IntReader[A] = Kleisli[scalaz.IdInstances#Id, Int, A]
type ValNEL[A] = ValidationNEL[Throwable, A]
val app = Applicative[IntReader].compose[ValNEL]
Now we can use a single |#| operation on the composed Applicative:
val f1 = toReader((x: Int) => Validation.success[NonEmptyList[Throwable], String](x.toString))
val f2 = toReader((x: Int) => Validation.success[NonEmptyList[Throwable], String]((x+1).toString))
val f3 = app.map2(f1, f2)(_ + ":" + _)
f3.run(5) should be_==(Validation.success("5:6"))
Say I have a list of names.
case class Name(val first: String, val last: String)
val names = Name("c", "B") :: Name("b", "a") :: Name("a", "B") :: Nil
If I now want to sort that list by last name (and if that is not enough, by first name), it is easily done.
names.sortBy(n => (n.last, n.first))
// List[Name] = List(Name(a,B), Name(c,B), Name(b,a))
But what, if I‘d like to sort this list based on some other collation for strings?
Unfortunately, the following does not work:
val o = new Ordering[String]{ def compare(x: String, y: String) = collator.compare(x, y) }
names.sortBy(n => (n.last, n.first))(o)
// error: type mismatch;
// found : java.lang.Object with Ordering[String]
// required: Ordering[(String, String)]
// names.sortBy(n => (n.last, n.first))(o)
is there any way that allow me to change the ordering without having to write an explicit sortWith method with multiple if–else branches in order to deal with all cases?
Well, this almost does the trick:
names.sorted(o.on((n: Name) => n.last + n.first))
On the other hand, you can do this as well:
implicit val o = new Ordering[String]{ def compare(x: String, y: String) = collator.compare(x, y) }
names.sortBy(n => (n.last, n.first))
This locally defined implicit will take precedence over the one defined on the Ordering object.
One solution is to extend the otherwise implicitly used Tuple2 ordering. Unfortunately, this means writing out Tuple2 in the code.
names.sortBy(n => (n.second, n.first))(Ordering.Tuple2(o, o))
I'm not 100% sure what methods you think collator should have.
But you have the most flexibility if you define the ordering on the case class:
val o = new Ordering[Name]{
def compare(a: Name, b: Name) =
3*math.signum(collator.compare(a.last,b.last)) +
math.signum(collator.compare(a.first,b.first))
}
names.sorted(o)
but you can also provide an implicit conversion from a string ordering to a name ordering:
def ostring2oname(os: Ordering[String]) = new Ordering[Name] {
def compare(a: Name, b: Name) =
3*math.signum(os.compare(a.last,b.last)) + math.signum(os.compare(a.first,b.first))
}
and then you can use any String ordering to sort Names:
def oo = new Ordering[String] {
def compare(x: String, y: String) = x.length compare y.length
}
val morenames = List("rat","fish","octopus")
scala> morenames.sorted(oo)
res1: List[java.lang.String] = List(rat, fish, octopus)
Edit: A handy trick, in case it wasn't apparent, is that if you want to order by N things and you're already using compare, you can just multiply each thing by 3^k (with the first-to-order being multiplied by the largest power of 3) and add.
If your comparisons are very time-consuming, you can easily add a cascading compare:
class CascadeCompare(i: Int) {
def tiebreak(j: => Int) = if (i!=0) i else j
}
implicit def break_ties(i: Int) = new CascadeCompare(i)
and then
def ostring2oname(os: Ordering[String]) = new Ordering[Name] {
def compare(a: Name, b: Name) =
os.compare(a.last,b.last) tiebreak os.compare(a.first,b.first)
}
(just be careful to nest them x tiebreak ( y tiebreak ( z tiebreak w ) ) ) so you don't do the implicit conversion a bunch of times in a row).
(If you really need fast compares, then you should write it all out by hand, or pack the orderings in an array and use a while loop. I'll assume you're not that desperate for performance.)