我在一些项目的过程中开发了一种用于创建不可变(只读)对象和不可变对象图的模式.不可变对象具有100%线程安全的优点,因此可以跨线程重用.在我的工作中,我经常在Web应用程序中使用此模式来配置设置以及我在内存中加载和缓存的其他对象.缓存对象应始终是不可变的,因为您希望保证它们不会意外更改.
现在,您可以轻松地设计不可变对象,如下例所示:
public class SampleElement
{
private Guid id;
private string name;
public SampleElement(Guid id, string name)
{
this.id = id;
this.name = name;
}
public Guid Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
}
Run Code Online (Sandbox Code Playgroud)
这对于简单的类来说很好 - 但是对于更复杂的类,我不喜欢通过构造函数传递所有值的概念.在属性上设置setter是更理想的,构建新对象的代码更容易阅读.
那么如何使用setter创建不可变对象?
好吧,在我的模式中,对象开始是完全可变的,直到你用一个方法调用冻结它们.一旦一个对象被冻结,它将永远保持不变 - 它不能再次变成一个可变对象.如果您需要对象的可变版本,则只需克隆它即可.
好的,现在谈谈一些代码.我在下面的代码片段中试图将模式简化为最简单的形式.IElement是所有不可变对象必须最终实现的基接口.
public interface IElement : ICloneable
{
bool IsReadOnly { get; }
void MakeReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
Element类是IElement接口的默认实现:
public abstract class Element : IElement
{
private bool immutable;
public …Run Code Online (Sandbox Code Playgroud) 问题很简单:我无法理解Zipper数据结构.
我的问题与它在树上的用法有关.
我想了解如何使用zipper更改树节点.以及如何不复制整棵树(或大部分).
请澄清拉链是否有问题.也许它无法帮助树更新?
或者,也许,有可能更新树,我只是看不到路?
是否有用于执行Scala代码静态分析的工具,类似于FindBugs和PMD for Java或Splint for C/C++?我知道FindBugs可以处理编译Java所产生的字节码,所以我很好奇它如何在Scala上运行.
谷歌搜索(截至2009年10月27日)显示的很少.
谷歌搜索(截至2010年2月1日)揭示了这个问题.
如何用纯函数式语言编写双向链表?也就是说,像Haskell这样的东西,你不在Monad,所以你没有变异.可能吗?(单链表很明显很简单).
我对这是什么有一个粗略的想法,但如果有人对"表达问题"的解释他们认为简洁直观我很乐意听到它.
computer-science programming-languages functional-programming
我正在学习Swift语言,但是我无法将可选的回调参数传递给函数:
func dismiss(completion: () -> Void) {
if (completion) {
return self.dismissViewControllerAnimated(true, completion: completion)
}
self.dismissModalViewControllerAnimated(true)
}
Run Code Online (Sandbox Code Playgroud)
这显示了一个错误 - Type () -> Void does not conform to protocol 'LogicValue'
有什么建议?
我对Scala的新手在尝试阅读David Pollack的Beggining Scala时有点新意.他定义了一个简单的递归函数,它从文件中加载所有字符串:
def allStrings(expr: => String): List[String] = expr match {
case null => Nil
case w => w :: allStrings(expr)
}
Run Code Online (Sandbox Code Playgroud)
它优雅而且很棒,只是当我试图加载一个庞大的字典文件时它抛出了一个StackOverflow异常.
现在据我所知,Scala支持尾递归,因此函数调用不可能溢出堆栈,可能编译器无法识别它?所以经过一些谷歌搜索后我尝试了@tailrec注释来帮助编译器,但它说
error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
def allStrings(expr: => String): List[String] =
Run Code Online (Sandbox Code Playgroud)
我理解尾递归错了吗?我该如何修复此代码?
所以我开始围绕Monads(在Haskell中使用).我很好奇IO或状态可以用纯函数语言处理的其他方式(理论上或现实中).例如,有一种名为"mercury"的逻辑语言使用"效果打字".在诸如haskell之类的程序中,效果打字工作会如何?其他系统如何运作?
我试图了解结果
(*) . (+)
Run Code Online (Sandbox Code Playgroud)
在哈斯克尔.我知道合成算子只是数学函数的标准组成 - 所以
(f . g) = f (g x)
Run Code Online (Sandbox Code Playgroud)
但:
(*) . (+) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)
我很难理解这种类型的签名.我希望能够做到这样的事情:
((*) . (+)) 1 2 :: Num a => a -> a
= (* (+ 1 2))
Run Code Online (Sandbox Code Playgroud)
的意义是什么 (*) .(+)的签名?我尝试用它来玩它(只是匹配它的签名):
((*) . (+)) 1 (\x -> x + 1) 1
Run Code Online (Sandbox Code Playgroud)
但那无法编译.我正在尝试在编写这些步骤时完成逻辑步骤,但我还没有完全理解它是如何得到这个结果的(以及结果是什么).