标签: structural-typing

从宏中获取具有匿名类方法的结构类型

假设我们要编写一个定义具有某些类型成员或方法的匿名类的宏,然后创建该类的实例,该类通过这些方法静态地键入为结构类型等.这可以通过2.10中的宏系统实现. 0,类型成员部分非常容易:

object MacroExample extends ReflectionUtils {
  import scala.language.experimental.macros
  import scala.reflect.macros.Context

  def foo(name: String): Any = macro foo_impl
  def foo_impl(c: Context)(name: c.Expr[String]) = {
    import c.universe._

    val Literal(Constant(lit: String)) = name.tree
    val anon = newTypeName(c.fresh)

    c.Expr(Block(
      ClassDef(
        Modifiers(Flag.FINAL), anon, Nil, Template(
          Nil, emptyValDef, List(
            constructor(c.universe),
            TypeDef(Modifiers(), newTypeName(lit), Nil, TypeTree(typeOf[Int]))
          )
        )
      ),
      Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
    ))
  }
}
Run Code Online (Sandbox Code Playgroud)

(提供我方法ReflectionUtils便利特性在哪里constructor.)

这个宏允许我们将匿名类的类型成员的名称指定为字符串文字:

scala> MacroExample.foo("T")
res0: AnyRef{type T = Int} = $1$$1@7da533f6
Run Code Online (Sandbox Code Playgroud)

请注意,它是适当的键入.我们可以确认一切都按预期工作:

scala> implicitly[res0.T =:= Int] …
Run Code Online (Sandbox Code Playgroud)

macros scala structural-typing scala-2.10 scala-macros

182
推荐指数
1
解决办法
8576
查看次数

鸭子打字,它必须是动态的吗?

维基百科曾经说*关于鸭子打字:

在使用面向对象编程语言的计算机编程中,duck typing是一种动态类型,其中对象的当前方法和属性集确定有效语义,而不是从特定类或特定接口的实现继承.

(*Ed.注意:自从发布此问题以来,维基百科文章已经过编辑,删除了"动态"一词.)

它说关于结构类型:

结构类型系统(或基于属性的类型系统)是类型系统的主要类,其中类型兼容性和等价性由类型的结构决定,而不是通过显式声明.

它将结构子类型与鸭子类型进行对比,如下所示:

[结构系统]与... duck typing相反,其中仅检查在运行时访问的结构的一部分的兼容性.

然而,术语鸭子打字在我看来至少是直观地包含结构子打字系统.实际上维基百科说:

这个概念的名称[鸭子打字]是指鸭子测试,归功于James Whitcomb Riley,其措辞可能如下:"当我看到一只鸟像鸭子一样散步,像鸭子一样游动,像鸭子一样呱呱叫,我称这只鸟为鸭子."

所以我的问题是:为什么我不能将结构子类型称为鸭子打字?是否存在动态类型语言,这些语言也不能被归类为鸭子类型?

后记:

正如有人叫daydreamdrunk上reddit.com如此雄辩地提出,它 "如果它编译像鸭子,像鸭子链接..."

后后记

许多答案似乎基本上只是重复我已经在这里引用的内容,而没有解决更深层次的问题,这就是为什么不使用术语duck-typing来涵盖动态类型和结构子类型?如果您只想谈论鸭子类型而不是结构子类型,那么只需调用它:动态成员查找.我的问题是没有关于鸭子打字这个术语对我说,这只适用于动态语言.

type-systems duck-typing language-design definitions structural-typing

24
推荐指数
6
解决办法
3837
查看次数

关于Scala中(递归)结构类型的有趣观察

我在一些代码中需要一些递归结构类型,使用特征和结构类型作为类型参数约束.它工作正常,但后来我了解到Scala不支持递归结构类型.

那么有人可以解释为什么这样可行:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {}
defined trait Test
Run Code Online (Sandbox Code Playgroud)

而这不是:

scala> def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null
<console>:5: error: illegal cyclic reference involving type M
       def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null
Run Code Online (Sandbox Code Playgroud)

scala structural-typing

24
推荐指数
1
解决办法
1338
查看次数

Scala中的模式匹配结构类型

为什么打印wtf?模式匹配不适用于结构类型吗?

  "hello" match {
    case s: { def doesNotExist(i: Int, x: List[_]): Double } => println("wtf?")
    case _ => println("okie dokie")
  }
Run Code Online (Sandbox Code Playgroud)

scala pattern-matching structural-typing

21
推荐指数
2
解决办法
3807
查看次数

C#是否与Scala的结构类型相当?

在Scala中,我可以定义结构类型如下:

type Pressable = { def press(): Unit }

这意味着我可以定义一个函数或方法,它将一个可压缩的参数作为参数,如下所示:

def foo(i: Pressable) { // etc.

我传递给这个函数的对象必须为它定义一个名为press()的方法,该方法匹配类型中定义的类型签名 - 不带参数,返回Unit(Scala的void版本).

我甚至可以使用结构类型内联:

def foo(i: { def press(): Unit }) { // etc.

它基本上允许程序员拥有鸭子类型的所有好处,同时仍然具有编译时类型检查的好处.

C#有类似的东西吗?我用谷歌搜索但找不到任何东西,但我不熟悉C#的任何深度.如果没有,有没有计划添加这个?

c# type-systems scala duck-typing structural-typing

18
推荐指数
3
解决办法
2012
查看次数

什么是TypeScript中的"接口结构类型"

Mark Rendle 在他关于TypeScript的博客文章中说,他喜欢的一件事是:

"接口的结构类型.我真的希望C#可以做到这一点"

那是什么意思?

c# structural-typing typescript

18
推荐指数
1
解决办法
1493
查看次数

为什么scala使用反射来调用结构类型的方法?

如果函数接受结构类型,则可以定义为:

def doTheThings(duck: { def walk; def quack }) { duck.quack }
Run Code Online (Sandbox Code Playgroud)

要么

type DuckType = { def walk; def quack  }
def doTheThings(duck: DuckType) { duck.quack }
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过以下方式使用该功能:

class Dog {
    def walk { println("Dog walk") }
    def quack { println("Dog quacks") }
}

def main(args: Array[String]) {
    doTheThings(new Dog);
}
Run Code Online (Sandbox Code Playgroud)

如果您为我的示例反编译(到Java)scalac生成的类,您可以看到该参数doTheThings是类型的Object,并且实现使用反射来调用参数上的方法(即duck.quack)

我的问题是为何反思?是不是可以只使用匿名和invokevirtual而不是反射?

下面是方法来翻译(执行)的结构型呼叫我的例子(Java语法,但问题是字节码):

class DuckyDogTest {
  interface DuckType {
    void walk();
    void quack();
  }

  static void doTheThing(DuckType d) {
    d.quack(); …
Run Code Online (Sandbox Code Playgroud)

scala structural-typing

16
推荐指数
2
解决办法
2591
查看次数

接受scala中参数的多个类型

我有两个对象,ObjectA和ObjectB,都有方法update().我想编写一个接受ObjectA或ObjectB(但没有其他类型)的函数.从概念上讲,这就是我要做的事情:

def doSomething[T <: ObjectA | T <: ObjectB](obj: T) = {
    obj.update
}
Run Code Online (Sandbox Code Playgroud)

我意识到还有其他方法可以解决这个问题(例如,update()方法的结构类型,公共基类等)但我的问题是它可以在Scala中这样做,如果是这样,语法是什么?这叫什么?

types scala structural-typing

16
推荐指数
1
解决办法
7524
查看次数

Scala:类型类和ADT之间的区别?

类型类和抽象数据类型之间有什么区别?

我意识到这对于Haskell程序员来说是一个基本的东西,但我来自Scala背景,并且会对Scala中的示例感兴趣.我现在能找到的最好的是类型类是"开放的"而ADT是"封闭的".将类型类与结构类型进行比较和对比也是有帮助的.

haskell scala abstract-data-type typeclass structural-typing

13
推荐指数
3
解决办法
7363
查看次数

Scala:通过包外的结构类型访问包可见方法

这不能按预期工作(因为我试图run从外部调用包私有Services):

object Services {
 class HelloPrinter {
   private[Services] def run = "Hello"
  }  
}

val obj = new Services.HelloPrinter
Run Code Online (Sandbox Code Playgroud)

但是,令人惊讶的是这有效:

val obj: {def run: String} = new Services.HelloPrinter
obj.run
Run Code Online (Sandbox Code Playgroud)

我会说,它是编译器中的一个错误,因为HelloPrinter由于包可见性规则而与结构类型不匹配,所以它根本不应该编译!

这是程序编译但抛出运行时异常(java.lang.NoSuchMethodException)的情况:

class HelloPrinter {
  private[HelloPrinter] def run = "Hello"
}  

val obj: {def run: String} = new HelloPrinter
obj.run
Run Code Online (Sandbox Code Playgroud)

这是我缺少的语言功能或规则,还是合法的Scala中的错误?

reflection scala access-modifiers nosuchmethoderror structural-typing

13
推荐指数
1
解决办法
190
查看次数