从选项中类型的方法生成部分应用的函数
假设我正在编写一个 GUI
class Kitteh (val age: Int) {
require (age < 5)
def saveMeow(file: File) = { /* implementation */ }
def savePurr(file: File) = { /* implementation */ }
}
该框架有一个当前 Kitteh 的字段,它是一个 Option
因为它可能尚未定义,或者用户可能尝试创建一个无效的选项:
var currentKitteh: Option[Kitteh] = None
时安全地创建一个 Kitteh
val a = ... // parse age from text box
currentKitteh = try { Some(new Kitteh(a)) } catch { case _ => None }
现在我想在用户点击 Create My GUI 两个按钮可以做类似的事情。在伪代码中,它们都应该
if (currentKitteh.isDefined) {
if (file on the disk already exists) {
bring up a dialog box asking for confirmation
if (user confirms)
<< execute method on currentKitteh >>
}
}
else bring up warning dialog
不用担心细节:重点是因为存在代码重复,所以我想创建一个可以从两个按钮调用的通用方法。唯一的区别是 Kitteh 上需要执行的方法。
现在,如果 currentKitteh
不是 Option
,那么通用方法可以有一个签名,例如
def save(filename: String, f:(File => Unit)) {
我可以使用它来调用,
save("meow.txt", currentKitteh.saveMeow _)
但由于它实际上是一个选项,我该如何实现这?
我可以检查 currentKitteh 是否已定义,并在为每个按钮调用 save
方法之前执行 .get
操作,但是还有另一种方法吗? >保存方法?换句话说,给定一个 Option[A]
,是否可以从(可能不存在的)A
对象上的方法指定部分函数?
(希望这个问题有意义,尽管例子很复杂)
编辑:额外问题:如果我使用 Either[Throwable, Kitteh,而不是
?Option[Kitteh]
,会怎么样? ]
更新:向伪代码添加附加行以弹出警告对话框:理想情况下,应始终调用 save
方法,以便在没有有效的 Kitteh 进行保存时向用户发出警告。
Suppose I'm writing a GUI
class Kitteh (val age: Int) {
require (age < 5)
def saveMeow(file: File) = { /* implementation */ }
def savePurr(file: File) = { /* implementation */ }
}
The frame has a field for the current Kitteh, which is an Option
because it might not have been defined yet, or the user may have attempted to create an invalid one:
var currentKitteh: Option[Kitteh] = None
Now I want to create a Kitteh
safely when the user hits Create
val a = ... // parse age from text box
currentKitteh = try { Some(new Kitteh(a)) } catch { case _ => None }
My GUI has two buttons which do similar things. In psedocode, they should both
if (currentKitteh.isDefined) {
if (file on the disk already exists) {
bring up a dialog box asking for confirmation
if (user confirms)
<< execute method on currentKitteh >>
}
}
else bring up warning dialog
Don't worry about the detail: the point is that because there is code duplication, I want to create a common method that I can call from both buttons. The only difference is the method on the Kitteh that needs to be executed.
Now if currentKitteh
were not an Option
, the common method could have a signature like
def save(filename: String, f:(File => Unit)) {
which I could call with, for example
save("meow.txt", currentKitteh.saveMeow _)
but since it is actually an Option, how could I implement this?
I could just check whether currentKitteh is defined, and do a .get
before calling the save
method for each button, but is there another way, leaving this check in the save
method? In other words, given an Option[A]
, is it possible to specify a partial function from a method on the (possibly non-existent) A
object?
(hope this question makes sense, convoluted example notwithstanding)
edit: Bonus question: what if, instead of Option[Kitteh]
, I used Either[Throwable, Kitteh]
?
update: Additional line added to pseudocode to bring up warning dialog: ideally, the save
method should always be called so that the user is warned if there is no valid Kitteh to save.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这对我来说看起来是最好的选择:
如果你重复这样做,你可以抽象它,
我想回答你原来的问题,你也可以将逻辑推入函数参数中,
语义与这个版本有点不同。
更新。如果将
k: Option[Kitteh]
替换为k: Either[Throwable, Kitteh]
,那么k.right foreach { c =>; ... }
?如果您想保留错误信息,您还可以使用k.right map ...
。针对修改后的问题,这里有另一种抽象可能性,
现在
save
有责任解压currentKitteh
。像这样调用save
,或者像这样,
This looks like the best option to me:
If you're repeatedly doing this, you can abstract it,
I suppose to answer your original question, you could also push the logic into the function argument,
The semantics are a little different with this version.
Update. If
k: Option[Kitteh]
is replaced byk: Either[Throwable, Kitteh]
, then what aboutk.right foreach { c => ... }
? You could also usek.right map ...
if you want to preserve error information.In response to the modified question, here's another abstraction possibility,
Now
save
has the responsibility of unpackingcurrentKitteh
. Callsave
like this,or like this,
您可以将一个函数映射到它并 getOrElse 您的失败函数:
然后您只需:
You can map a function to it and getOrElse your fail function:
then you just:
您可以定义一个 BadKitteh 类并让它产生错误消息。如果您需要的话,只需使用 currentKitty.getOrElse(badKitty) 即可。
You could define a class BadKitteh and have that produce error messages. Then simply use currentKitty.getOrElse(badKitty) if you need one.