来自C#背景,我想说ref
关键字在某些情况下非常有用,在这些情况下,希望对方法参数进行更改,以直接影响用于将参数设置为{的值类型的传递值{1}}。
此外,当返回大量各种逻辑上未连接的值时,null
关键字可以派上用场。
我的问题是:是否可以通过Haskell中的引用将参数传递给函数?如果没有,直接替代方案(如果有的话)是什么?
答案 0 :(得分:7)
在Haskell和ML等语言中,“pass-by-value”和“pass-by-reference”之间没有区别,因为无法分配这些语言中的变量。在影响任何传递的变量时,首先不可能对方法参数进行“更改”。
答案 1 :(得分:5)
我的问题是:是否可以通过Haskell中的引用将参数传递给函数?如果没有,直接替代方案(如果有的话)是什么?
不,Haskell中的值是不可变的(好吧,do
符号可以创建一些可变性的错觉,但它都发生在函数内部并且是完全不同的主题)。如果要更改值,则必须返回更改的值并让调用者处理它。例如,请参阅随机数生成函数next
,它返回值和更新的RNG。
此外,当返回大量各种逻辑上未连接的值时,out关键字可以派上用场。
因此,您也不能拥有out
。如果你想返回几个完全断开连接的值(此时你应该想到为什么从单个函数返回断开的值),返回一个元组。
答案 2 :(得分:5)
这取决于背景。没有任何背景,不,你不能(至少不是你的意思)。有了上下文,如果你愿意,你很可能会这样做。特别是,如果您在IO
或ST
工作,则可以分别使用IORef
或STRef
,以及可变数组,向量,哈希表,弱哈希表(仅限IO
,我相信)等。函数可以采用其中的一个或多个,并产生一个动作(执行时)将修改这些引用的内容。
另一种上下文StateT
给出了纯粹实现的可变“状态”值的错觉。您可以使用复合状态并将镜头传递到其中,为某些目的模拟参考。
答案 3 :(得分:0)
不,这是不可能的,因为Haskell变量是不可变的,因此,Haskell的创建者必须有理由认为没有必要传递无法更改的引用。
考虑一个Haskell变量:
let x = 37
要更改此设置,我们需要创建一个临时变量,然后将第一个变量设置为该临时变量(进行修改)。
let tripleX = x * 3
let x = tripleX
如果Haskell已通过引用,我们可以这样做吗?
答案是否。
假设我们尝试过:
tripleVar :: Int -> IO()
tripleVar var = do
let times_3 = var * 3
let var = times_3
此代码的问题是最后一行;尽管我们可以想象变量是通过引用传递的,但新变量不是。
换句话说,我们要引入一个新的具有相同名称的 local 变量;
再看看最后一行:
let var = times_3
Haskell不知道我们要“更改”全局变量。由于我们无法重新分配它,因此我们将在本地范围内创建一个具有相同名称的新变量,从而不会更改引用。 :-(
tripleVar :: Int -> IO()
tripleVar var = do
let tripleVar = var
let var = tripleVar * 3
return()
main = do
let x = 4
tripleVar x
print x -- 4 :(