揭开函数定义的神秘面纱 [英] Demystifying a function definition

查看:39
本文介绍了揭开函数定义的神秘面纱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Scala 的新手,我希望这个问题不是太基本.我在网上找不到这个问题的答案(可能是因为我不知道相关的关键字).

我试图理解以下定义:

def functionName[T <: AnyRef](name: Symbol)(range: String*)(f: T => String)(implicit tag: ClassTag[T]): DiscreteAttribute[T] ={val r = ....new anotherFunctionName[T](name.toString, f, Some(r))}

  • 首先,为什么定义为def functionName[...](...)(...)(...)(...)?我们不能把它定义为 def functionName[...](..., ..., ..., ...) 吗?
  • 二、range:String*如何从range:String?
  • 第三,如果implicit tag: ClassTag[T]不存在会不会有问题?

解决方案

首先,为什么定义为 def functionName...(...)(...)(...)?不能定义为 def functionName[...](..., ..., ..., ...) 吗?

使用柯里化的一个很好的理由是支持类型推断.考虑这两个函数:

def pred1[A](x: A, f: A => Boolean): Boolean = f(x)def pred2[A](x: A)(f: A => Boolean): Boolean = f(x)

因为如果你尝试像这样调用 pred1 ,类型信息是从左到右流动的:

pred1(1, x => x > 0)

x => 的类型×>0 还不能确定,你会得到一个错误:

:22: 错误:缺少参数类型pred1(1, x => x > 0)^

要使其工作,您必须指定匿名函数的参数类型:

pred1(1, (x: Int) => x > 0)

pred2 可以在不指定参数类型的情况下使用:

pred2(1)(x => x > 0)

或者简单地说:

pred2(1)(_ > 0)

<块引用>

二、range: String* from range: String 怎么做?

它是定义 重复参数又名可变参数.忽略其他差异,它只能用于最后一个位置,并且可以作为 scala.Seq 使用(这里是 scala.Seq[String]).典型的用法是集合类型的 apply 方法,它允许像 SomeDummyCollection(1, 2, 3) 这样的语法.更多内容请看:

<块引用>

第三,如果隐式标签:ClassTag[T]不存在会不会有问题?

正如 Aivean 所述,这里不应该是这种情况.ClassTags 由编译器自动生成,只要类存在就应该可以访问.在一般情况下,如果无法访问隐式参数,您将收到错误消息:

scala>导入 scala.concurrent._导入 scala.concurrent._标度>val 答案:Future[Int] = Future(42)<console>:13: 错误:找不到隐式的 ExecutionContext.你可能会通过方法的(隐式 ec:ExecutionContext)参数或导入 scala.concurrent.ExecutionContext.Implicits.global.val 答案:Future[Int] = Future(42)

I am new to Scala, and I hope this question is not too basic. I couldn't find the answer to this question on the web (which might be because I don't know the relevant keywords).

I am trying to understand the following definition:

def functionName[T <: AnyRef](name: Symbol)(range: String*)(f: T => String)(implicit tag: ClassTag[T]): DiscreteAttribute[T] = {
    val r = .... 
    new anotherFunctionName[T](name.toString, f, Some(r))
  }

  • First , why is it defined as def functionName[...](...)(...)(...)(...)? Can't we define it as def functionName[...](..., ..., ..., ...)?
  • Second, how does range: String* from range: String?
  • Third, would it be a problem if implicit tag: ClassTag[T] did not exist?

解决方案

First , why is it defined as def functionName...(...)(...)(...)? Can't we define it as def functionName[...](..., ..., ..., ...)?

One good reason to use currying is to support type inference. Consider these two functions:

def pred1[A](x: A, f: A => Boolean): Boolean = f(x)
def pred2[A](x: A)(f: A => Boolean): Boolean = f(x)

Since type information flows from left to right if you try to call pred1 like this:

pred1(1, x => x > 0)

type of the x => x > 0 cannot be determined yet and you'll get an error:

<console>:22: error: missing parameter type
              pred1(1, x => x > 0)
                       ^

To make it work you have to specify argument type of the anonymous function:

pred1(1, (x: Int) => x > 0)

pred2 from the other hand can be used without specifying argument type:

pred2(1)(x => x > 0)

or simply:

pred2(1)(_ > 0)

Second, how does range: String* from range: String?

It is a syntax for defining Repeated Parameters a.k.a varargs. Ignoring other differences it can be used only on the last position and is available as a scala.Seq (here scala.Seq[String]). Typical usage is apply method of the collections types which allows for syntax like SomeDummyCollection(1, 2, 3). For more see:

Third, would it be a problem if implicit tag: ClassTag[T] did not exist?

As already stated by Aivean it shouldn't be the case here. ClassTags are automatically generated by the compiler and should be accessible as long as the class exists. In general case if implicit argument cannot be accessed you'll get an error:

scala> import scala.concurrent._
import scala.concurrent._

scala> val answer: Future[Int] = Future(42)
<console>:13: error: Cannot find an implicit ExecutionContext. You might     pass
an (implicit ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
       val answer: Future[Int] = Future(42)

这篇关于揭开函数定义的神秘面纱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆