scala - Scala 中的装饰器模式
问题描述
我在 Scala 中有以下代码。我有几个关于功能和语法的问题。
type Logger = String => Unit
type Decorator = Logger => Logger
val uppercase: Decorator =
logger =>
(msg: String) => logger(msg.toUpperCase)
val info: Decorator =
logger =>
(msg:String) => logger("info " + msg)
我是否理解正确,那Decorator
是ìnfo
函数的输入?
为什么这里不需要声明返回类型?
然后我使用这样的代码:
val prefixUppercase = info(uppercase(println(_)))
为什么我可以println(_)
传到uppercase
?
该uppercase
函数需要一个 type 的参数Decorator
,这println()
显然不是。
另外我使用println(_)
,但是当我尝试传递这样的命名参数时,println(x)
我得到一个错误。
解决方案
我是否理解正确,那
Decorator
是ìnfo
函数的输入?
val info: Decorator =
logger =>
(msg:String) => logger("info " + msg)
不,Decorator
是的类型。info
info
被声明为一个函数 from Logger
to Logger
(这就是Decorator
扩展的内容)。
val info: Decorator = // info is a Decorator
// i.e. a function Logger => Logger
logger => // so this makes logger a Logger
// (the input for the Decorator)
// what follows is the output of the Decorator
// i.e. another Logger
// i.e. a function String => Unit
(msg:String) => // so this is that String input to the
// resulting (decorated) Logger
logger("info " + msg) // and this is what our decorator does
// to the String to be logged:
// we prefix it with "info "
// and give it to the underlying logger
为什么这里不需要声明返回类型?
正在声明返回类型(见上文)。
info
一般来说,Scala 非常擅长推断类型,因此如果它可以从其他已知类型派生,您实际上不需要声明类型,但是
a) 良好的做法是声明非显而易见的类型,尤其是在公共值上。这可用作文档,加快编译速度并避免错误(如果推断的类型不是您想要的,它有助于跟踪问题)
b)在您的情况下,这也是让编译器知道logger
这里应该有什么类型的最直接的方法。否则,您将不得不在其他地方声明。
为什么我可以
println(_)
传到uppercase
?大写函数需要类型的参数Decorator
,这println()
显然不是。
uppercase
不需要 a Decorator
,uppercase
是a Decorator
,这意味着它是一个接受 aLogger
并返回 a的函数Logger
。
所以它需要 a Logger
,它是一个接受 aString
并且不返回任何内容的函数。println
就是这样一个函数,所以你可以将它传递给uppercase
(作为它的Logger
输入参数)。
我尝试像这样传递一个命名参数,但
println(x)
出现错误。
x
在这种情况下是什么?
您需要创建一个Logger
, 意味着一个接受 String 并且不返回任何特殊内容的函数。
x => println(x)
会做。
println(_)
是同一件事的简写,并且会做。
println(somethingElse)
或者println(123)
不再是接受 String 的函数(它们不再接受任何参数),所以那些不是Logger
s。
推荐阅读
- python - 使用 pandas Dataframe to_string() 方法时出现 MemoryError
- kubernetes - 删除后 Kubernetes 重新附加到相同的持久卷
- node.js - 如何使用指数 (e) 和模数 (n) 生成 RSA 公钥来验证 json Web 令牌的签名?
- flutter - 同一棵树中同一肘(局部范围)的不同实例
- java - 使用 Scanner 从文件中读取整数的问题
- c# - EF Core 排除查询中的某些属性,多对多关系
- php - AH00052 子 pid xxxxx 退出信号 非法指令
- angular - ngx-graph 通常不会在 Angular 页面中加载
- python-3.x - Django:将价格注释到行,然后按字段对行进行分组,并将价格总和注释到组
- amazon-web-services - 如何通过用户名和密码在aws lambda函数中获取cognitoIdentityId