保留的问题 - 请参阅底部的编辑
我正在开发一个小型函数库,基本上是通过隐藏基本的圈复杂度来提供一些可读性.调用提供程序(调用Select<T>帮助程序工厂Select),用法类似于
public Guid? GetPropertyId(...)
{
return Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
.Or(IGuessWeCanTryThisTooIfWeReallyHaveTo(...))
//etc.
;
}
Run Code Online (Sandbox Code Playgroud)
和库会照顾短路,等我还添加了从隐式转换Select<T>来T的,所以我可以写
public Guid GetPropertyId(...)
{
ServiceResult result = Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...));
return result.Id;
}
Run Code Online (Sandbox Code Playgroud)
我真正希望能够做的是在没有赋值的情况下隐式转换为T:
public Guid GetPropertyId(...)
{
return
//This is the part that I want to be implicitly cast to a ServiceResult
Select
.Either(TryToGetTheId(...))
.Or(TrySomethingElseToGetTheId(...))
//Then I want to access this property on the result of the cast
.Id;
}
Run Code Online (Sandbox Code Playgroud)
但是,指定的语法不起作用 - 我必须将其分配给变量,或者显式地转换它.有没有办法获得内联隐式转换?
编辑 …
隐式转换似乎是Scala的一个主要且有争议的特性,而它们似乎在C#中的突出程度要小得多.它们在两种语言中有什么区别?有没有我在Scala中被迫使用implicits的地方,或者我总是可以选择是否希望转换是隐式的还是显式的,就像在C#中一样?通常在C#中,我喜欢明确地进行转换,以便维护程序员意图的类型检查,即使消费者是我自己.
我是否正确地说C#或Scala都不能隐式拆分或组合方法/函数参数?在def myMethod(v1:Int,v2:Int)中不接受Tuple2 [Int,Int]作为其参数列表,def yourMethod(v1:Tuple2 [Int,Int])将不接受两个整数作为其参数列表.据推测,语言设计者必须考虑隐式/显式参数分割/组合.当使用多个但相似的图形库的点结构时,我确实发现这个特性是可取的.
以下代码给出了错误:
package test
trait Base {
def method:String
}
trait Trait extends Base {
def method()(implicit i:String):String = { "2" }
}
object Object extends Trait {
}
Run Code Online (Sandbox Code Playgroud)
错误是"对象创建不可能,因为类型为Base的方法方法=>字符串未定义"
以下错误由以下代码修复
package test
trait Base {
def method:String
}
trait Trait extends Base {
def method:String = method()("String") // Over loading
def method()(implicit i:String):String = { "2" }
}
object Object extends Trait {
}
Run Code Online (Sandbox Code Playgroud)
现在我代替Scala类,当我定义一个Java接口时,如下所示:
// Java Code
package test;
public interface JBase {
String method();
}
// Scala …Run Code Online (Sandbox Code Playgroud) 我有一个具有以下签名的函数:
myFunc[T <: AnyRef](arg: T)(implicit m: Manifest[T]) = ???
Run Code Online (Sandbox Code Playgroud)
如果在编译时我不知道参数的确切类型,我该如何调用此函数?
例如:
val obj: AnyRef = new Foo() // At compile time obj is defined as AnyRef,
val objClass = obj.getClass // At runtime I can figure out that it is actually Foo
// Now I would need to call `myFunc[Foo](obj.asInstanceOf[Foo])`,
// but how would I do it without putting [Foo] in the square braces?
Run Code Online (Sandbox Code Playgroud)
我想写一些逻辑类似的东西:
myFunc[objClass](obj.asInstanceOf[objClass])
Run Code Online (Sandbox Code Playgroud)
谢谢!
更新:
问题是无效的 - 正如@DaoWen,@ Jermo和@itsbruce正确指出的那样,我试图做的事情完全是胡说八道!我只是严厉地推翻了这个问题.感谢你们!太糟糕了我不能接受所有答案正确:)
所以,问题是由以下情况引起的:
我正在使用Salat库将对象序列化为BSON/JSON表示/从BSON/JSON表示.
Salat有一个Grater[T]用于序列化和反序列化的类.从BSON …
Scala中至少有两种技术可以将默认值传递给方法
1)默认参数值
scala> def f(i: Int = 0) = i
f: (i: Int)Int
scala> f()
res0: Int = 0
scala> f(1)
res1: Int = 1
Run Code Online (Sandbox Code Playgroud)
2)隐含参数
scala> def g(implicit i: Int) = i
g: (implicit i: Int)Int
scala> implicit val default = 0
default: Int = 0
scala> g(1)
res5: Int = 1
scala> g
res7: Int = 0
Run Code Online (Sandbox Code Playgroud)
在哪种情况下你选择一个或另一个?凭借隐式的力量,默认值是一个有用的功能吗?
假设我们有以下代码:
void ff(wchar_t*)
{
}
template<typename T>
void ffc(T&& a)
{
ff(std::forward<T>(a));
}
Run Code Online (Sandbox Code Playgroud)
为什么ff(0)允许通话,但ffc(0)不是?
JsonWriter[T]当调用toJson一个实例时,spray-json依赖于一个范围内的隐式存在T.
假设我有一个具有几个具体子类型的特征,每个子类型都有一个JsonWriter:
trait Base
case class Foo(a: Int) extends Base
case class Bar(a: Int, b: Int) extends Base
implicit val FooFormat = jsonFormat1(Foo)
implicit val BarFormat = jsonFormat2(Bar)
def go(o: Base) = {
o.toJson
}
Run Code Online (Sandbox Code Playgroud)
go不编译,因为有一个为基地没有JsonWriter,即使是对所有具体的子类型的作家.
如何重新组织此代码,以便Base使用适当的json格式化程序的通用函数?
在下面的代码中,我尝试使用shapeless派生类型类实例.但是,在更复杂的案例类(转换为更复杂的HList)的情况下,编译器给我一个"分歧的隐式扩展",即使它似乎没有两次解析相同类型的隐式类型.也许我错过了编译器的其他一些规则?
(小提琴:https://scalafiddle.io/sf/WEpnAXN/0)
import shapeless._
trait TC[T]
sealed trait Trait1
case class SimpleClass(a: String) extends Trait1
sealed trait Trait2
case class ComplexClass(a: String, b: String) extends Trait2
object Serialization extends App {
//Instances for HList
implicit val hnilInstance: TC[HNil] = ???
implicit def hconsInstance[H, T <: HList] (implicit t: TC[T]): TC[H :: T] = ???
//Instances for CoProduct
implicit val cnilInstance: TC[CNil] = ???
implicit def cconsInstance[H, T <: Coproduct] (implicit h: TC[H], t: TC[T]): TC[H :+: …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
trait Foo {
type T
def value: T
}
object Foo {
def apply[A](v: A): Foo = new Foo {
override type T = A
override def value = v
}
}
trait Decode[A] {
def apply(x: A): String
}
object Decode {
def apply[A](f: A => String): Decode[A] = new Decode[A] {
override def apply(x: A) = f(x)
}
implicit val decodeStr: Decode[String] = Decode(identity)
}
class Sandbox {
def decodeFoo(foo: Foo)(implicit decoder: Decode[foo.T]): String =
decoder(foo.value)
val …Run Code Online (Sandbox Code Playgroud) 为什么下面的代码不选择最接近的超类型的隐式val?
class A
class B extends A
trait TC[-T] { def show(t: T): String }
implicit val showA = new TC[A] { def show(a: A): String = "it's A" }
implicit val showB = new TC[B] { def show(b: B): String = "it's B" }
def doit[X](x: X)(implicit tc: TC[X]): Unit = println(tc.show(x))
doit(new A) // "it's A" as expected
doit(new B) // "it's A" ... why does this not give "it's B" ???
Run Code Online (Sandbox Code Playgroud)
如果使TC不变(即trait TC[T] (...) …