它们通常使用语言的非功能方面(包括可变变量).还有其他策略吗?你能描述一下吗?
这是一个Haskell问题,但我也对其他语言的答案感兴趣.有没有办法自动翻译纯函数代码,编写处理列表或不可变数组而不进行任何破坏性更新,代码使用可变数组提高效率?
在Haskell中,生成的代码将在STmonad中运行(在这种情况下它将全部包装在runST或中runSTArray)或在IOmonad中运行,我假设.
我最感兴趣的是适用于任何元素类型的通用解决方案.
我以为我以前见过这个,但我不记得在哪里.如果它还不存在,我有兴趣创建它.
我正在尝试Map使用默认值创建一个mutable ,ListBuffer当请求的元素尚未在地图中时,该默认值会创建一个新的.但是,虽然新地图作为默认值返回,但它不会保留在地图中.也许这就是它的工作方式,我想,但是当我用一个Int而不是ListBuffer它测试它时它完全按照我想要的方式进行测试.这里有一些代码来解释我的意思 - 我做错了什么?
首先,它在这里使用Map[Int]:
scala> val a = collection.mutable.Map(1 -> 1).withDefault(i => 0)
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)
scala> a(1) += 1 // adding to an existing element works as expected
scala> a
res48: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)
scala> a(2) += 1 // what about adding to a non-existing element?
scala> a // the new element has been added to the map
res50: scala.collection.mutable.Map[Int,Int] = Map(1 -> …Run Code Online (Sandbox Code Playgroud) 编者注:这个问题早于Rust 0.1(标记为2013-07-03),并且在语法上不是有效的Rust 1.0代码.答案可能仍包含有价值的信息.
有谁知道如何在Rust中创建可变的二维向量并将它们传递给要操作的函数?
这是我到目前为止所尝试的:
extern crate std;
fn promeni(rec: &[u8]) {
rec[0][1] = 0x01u8;
}
fn main() {
let mut rec = ~[[0x00u8,0x00u8],
[0x00u8,0x00u8]
];
io::println(u8::str(rec[0][1]));
promeni(rec);
io::println(u8::str(rec[0][1]));
}
Run Code Online (Sandbox Code Playgroud) 我一直在阅读ocaml文档,但我不能解释如何{ x with ... }解决可变字段的问题.我发现的最接近的人说
6.7表达式
Run Code Online (Sandbox Code Playgroud)expr := ... ? { expr with field = expr { ; field = expr } [;] }...
记录
该表达式
{ expr with field1 = expr1 ; … ; fieldn = exprn }构建一个fields field1 … fieldn等于的新记录expr1 … exprn,并且所有其他字段具有与记录中相同的值expr.换句话说,它返回记录的浅表副本expr,但field1 … fieldn初始化为的字段除外expr1 … exprn.
"浅拷贝"措辞可以解释为mutable未提及的字段共享存储空间或可以引用嵌套记录.当我测试时(使用"The OCaml toplevel,版本4.00.1")因此
type t = { …Run Code Online (Sandbox Code Playgroud) 据我所知,在C++中,具有相同访问控制的类/成员以声明顺序存储在内存中.是下一个例子m,c应该一个接一个地存储:
#include <cstdlib>
#include <iostream>
struct X
{
mutable int m;
int c;
};
const X cx = {0, 1};
int main()
{
X& x = const_cast<X&>(cx);
x.m = rand();
x.c = rand();
std::cout<<x.m<<" "<<x.c;
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,程序运行并打印2个随机数.如果我删除mutable它崩溃,因为cx存储在只读保护的内存中.
这让我很奇怪 - 一个mutable成员是否禁用const整个优化struct(以某种方式使所有成员mutable)?
是否可以将struct只读存储器和其他部件中的部分存储在非只读存储器中并遵守C++标准存储器布局?
这是在Windows 7上使用Visual Studio 2010和在Ubuntu上使用GCC 4.7.2测试的.
我目前正在重新开发F#中的应用程序,虽然经验非常出色,但在控制可变性时我发现自己有点困惑.
以前,我的C#程序使用的文档模型是高度可变的,并实现了ObservableCollections和INotifyPropertyChanged,它们之间的共享状态不会出错.显然,这不是一个理想的选择,特别是如果我想要一个完全不可改变的设计方法.
考虑到这一点,我为我的底层应用程序内核创建了一个不可观察的,不可变的文档模型,但是,因为我希望UI订阅者看到更改,我立即发现自己实现了事件驱动模式:
// Raw data.
type KernelData = { DocumentContent : List<string> }
// Commands that act on the data.
type KernelCommands = { AddString : string -> () }
// A command implementation. Performs a state change, echos the new state through the event.
let addStringCommand (kernelState : KernelData) (kernelChanged : Event<KernelData>) (newString : string) =
kernelState with { DocumentContent=oldList |> List.add newString }
|> kernelChanged.Trigger
// Time to wire this up.
do
// Create some starting state. …Run Code Online (Sandbox Code Playgroud) 我最近一直在阅读很多关于价值类型和参考类型及其差异的文献.这个问题围绕着价值类型的可变性和不变性这一主题.
基于我所读到的,似乎.NET中的值类型应该以它们不可变的方式编写; 也就是说,一旦为它们分配了一个值,该类型在内存中的值永远不会改变.只有该类型的后续副本可以在内存中构造新实例,并使用基于原始值的新值.似乎.NET中的可变性是邪恶的.
为了澄清对不变性的理解(为了我自己的理智和其他人),我在下面证明了这一点:
DateTime并且TimeSpan是不可变结构的示例,因为一旦将值赋给实例,该实例值就不会改变,这通过只读属性很明显:
DateTime dt = new DateTime();
DateTime newdt = dt.AddDays(2); // Okay, new value stored in newdt
newdt.Year = 1945; // Error, cannot write to readonly property
Run Code Online (Sandbox Code Playgroud)
然而,当看到原始类型时,不变性可能会令人困惑Int32,Double或者Char,因为类型似乎是可变的,但我的直觉是实际上,通过CLR透明地处理不变性; 以下是一些操作(我在一些非常基本的x86中进行了评论,以了解如何根据原始类型处理不变性)
int x = 0;
// xor eax, eax; 'clear register to 0
// push eax; 'push eax (0) onto the stack
x = …Run Code Online (Sandbox Code Playgroud) 在使用首次可变矢量,我发现,虽然Data.Vector.Unboxed拥有所有你喜欢预期更高层次的功能map,fold等等,可变的版本Data.Vector.Unboxed.Mutable没有这些。尝试在可变向量上使用 immutable 包中的函数不起作用。
mutable vector 包缺少很多这些高级函数的原因是什么?
我收到“变异运算符的左侧不可变”..<“返回不可变值”错误
我阅读了关于变异值的另一篇文章,但我无法弄清楚这些解决方案是如何应用的。
代码(和评论):
//populate array of 3 random numbers using correct answer and 2 incorrect choices
func insertIntoArray3(_ randomNumber: Int) -> Int {
for intJ in 0 ..< 2 += 1{
if arrayIndex != 3 {
checkIfExists(randomNumber)
if ifExists {
let randomNumber = 1 + random() % 10
insertIntoArray3(randomNumber)
} else {
array3[arrayIndex] = (randomNumber)
arrayIndex = arrayIndex + 1
}
}
}
return randomNumber
}
Run Code Online (Sandbox Code Playgroud)
修订代码:
//populate array of 3 random numbers using correct answer and 2 incorrect choices …Run Code Online (Sandbox Code Playgroud)