TDPL,p.167:
只要函数中的可变状态完全是暂时的(即,在堆栈上分配)和私有(即,不通过引用可能污染它的函数传递),那么该函数可以被认为是纯的.
import std.stdio : writeln;
struct M{
int[4] _data;
pure ref int opIndex(size_t i){ return _data[i]; }
}
pure M foo(ref M m){
m[0] = 1234;
return m;
}
void main(){
M m1 = M([7, 7, 7, 7]);
writeln(m1);
foo(m1);
writeln(m1);
}
// output:
// M([7, 7, 7, 7])
// M([1234, 7, 7, 7])
Run Code Online (Sandbox Code Playgroud)
可变状态是暂时的,因为它在堆栈上,对吗?但它不是私密的.那怎么foo()允许修改m1?
纯函数可以调用外部方法吗?
例如:
class Dog {
function jump(name) {
return "a dog named " + name + " jumped!"
}
function jumpTwice(names) {
var result = [];
for (var i = 0; i < 2; i++) {
result.push(jump(names[i]));
}
return result.join("\n");
}
}
Run Code Online (Sandbox Code Playgroud)
可以jumpTwice()算是一个pure function?
React文档说:
React is pretty flexible but it has a single strict rule: all React components must act like pure functions with respect to their props.
这是为什么?
我猜想,如果您直接更改props的值,则组件不会重新渲染,这就是我们必须使用的原因setState。但我仍然不了解其背后的原因。为什么组件在其道具方面必须像纯函数一样?
纯函数可以在同一个类中使用私有常量变量吗?
例如:
class TimesThousand {
const CONSTANT = 1000;
function calculate(number) {
return number * CONSTANT;
}
}
Run Code Online (Sandbox Code Playgroud)
可以calculate()被认为是一个pure function?
在 Java(或任何类似的语言)中,如何编写从列表中删除元素的纯函数(或方法)。
如果该元素在列表中,我们只需返回一个新的(理想情况下不可变的)列表,其中包含输入列表的所有元素,减去我们删除的元素。
但是如果在列表中找不到该元素,您将如何处理?
假设该方法接收 2 个参数,即list和element要删除的参数:
public SOMETHING remove(final List<String> list, final String element){
// Copy the input list and remove the first occurrence of 'element', if I find it.
//
// if I don't find it ... do something clever here ...
}
Run Code Online (Sandbox Code Playgroud)
如果我调用这个方法,并且element不包含在里面list:
Optional.of(listCopy)(编辑:发布后添加到我的问题中)我应该提到,我只想删除第一次出现的element,因此如果输入list多次出现element,我不想通过对我的remove() 方法的一次调用来删除它们(例如使用stream().filter())来删除它们。我刚刚编辑了代码示例中的注释来反映这一点。然而,这与我的问题并不完全相关,因为我的主要问题围绕如何使该方法直观易用并保持“纯粹”。
我在上述建议的基础上添加了一个额外的想法。返回Optional.of(listCopy)似乎是迄今为止所提出的解决方案中最优雅的解决方案。它强制调用者检查请求的操作是否成功,并且(如果成功),它返回一个新列表,从而不会修改原始输入列表。如果操作不成功(element …
这个问题还有一个额外的限制,那就是IO尽可能避免。
这个限制最初是放在我的问题的最后,似乎很难被注意到。
我实际上知道如何在 Haskell 中实现我的目标,就像我知道如何在其他命令式编程语言中实现它一样 - 命令式方式。
但我没有使用任何其他命令式编程,对吗?我正在使用哈斯克尔。我想要一种 Haskell 方式,一种纯粹的方式。
我通过将额外限制重新定位在相对显眼的位置来重新组织我的问题。那是我的错。非常感谢这些快速回复。
main :: IO ()
main =
putStrLn =<< cachedOrFetched
<$> getLine
<*> getLine
cachedOrFetched :: String -> String -> String
cachedOrFetched cached fetched =
if not $ null cached
then cached
else fetched
Run Code Online (Sandbox Code Playgroud)
上面的代码执行了两次IO。但期望的行为是当第一个 IO 的结果不为 null 时跳过第二个 IO。
我知道我可以通过使用door来实现这一点when。鉴于使用太多dos 违反了我使用 Haskell 的初衷,我可能会接受when.
或者,还有更好的方法?更纯粹的方式?
大约两周前我开始学习 Haskell。我并不期待从中找到工作,只是被编程语言本身所吸引。因为据我所知这是“最纯粹的”。
起初,一切似乎都如我预期的那样好。但后来我发现我必须IO在我的纯代码中写 s 。我花了很长时间才找到一种控制不纯污染的方法。应用函子似乎是拯救者。
有了它,我可以将不纯的 IO“柯里化”到我的纯函数中,这样可以节省大量do,<- …
我知道
debug writeln("Some good debug message")
Run Code Online (Sandbox Code Playgroud)
在pure功能,但我已经仔细标记为@safe或的功能@trusted呢?DMD目前不允许使用debug writeln,因为writeln目前和类似@system.这是恕我直言,非常令人沮丧.有一个聪明的方式来逃避安全还是我暂时注释掉我所有的@safe和@trusted标签?
我正在学习Haskell并编写一个解决玩具问题的程序.在从文件读取参数之后,程序使用在运行时不会更改的参数k.我对使用纯函数非常陌生,我想尽可能多地编写纯函数.
我有一个数据类型Node,用于比较节点,获取节点的后代等等.目前,所有这些函数都将参数k作为参数,例如
compare k node1 node2 = ...
desc k node = ...
Run Code Online (Sandbox Code Playgroud)
每当我必须递归调用函数中的任何一个时,我必须重复k参数.这似乎是多余的,因为k对于这些函数永远不会有不同的值,因为它使类型签名的可读性降低,并且如果可能的话我想重构它.
是否有任何策略可以使用纯函数执行此操作,还是仅仅是我必须处理的限制?
我想到了什么
之前我在顶级硬编码k,它似乎工作(我能够在函数中使用k而不需要它作为显式参数).但是,一旦我需要从文件中读取输入,这显然是不可行的.
另一种可能的策略是在函数中定义所有这些main函数,但在Haskell中似乎强烈建议不要这样做.
我可以在javascript中编写以下代码:
function sum(num1, num2) {
return num1 + num2;
}
Run Code Online (Sandbox Code Playgroud)
然后得到一个值
var someNum = sum(2,5);
Run Code Online (Sandbox Code Playgroud)
我想在Powershell中做同样的事情,但我阅读了以下指南:
PowerShell也知道return关键字; 然而,它遵循不同的逻辑.通常,返回的目的是结束代码段的执行并将控件返回给父块.
如果向return语句添加参数,则该值将确实返回到调用子例程.但是,这也适用于具有输出的所有其他语句.这意味着函数中产生的任何输出都将与返回参数一起存储在变量中.
我想为了拥有纯粹的功能而这样做.但是,它似乎正在做
var someNum = sum(2,5);
完全是多余的,当我可以调用上面的函数,定义someNum它的内部,它将在全局范围内可用.
我错过了什么或者是否有可能在Powershell中编写纯函数而不返回函数内部的所有内容?
有点切,但这是我的实际代码:
function GetPreviousKeyMD5Hashes() {
$query = "SELECT Name, MD5, executed FROM [AMagicDb].[dbo].cr_Scripts";
$command = New-Object System.Data.SQLClient.SQLCommand;
$command.Connection = $connection;
$command.CommandText = $query;
try {
$reader = $command.ExecuteReader();
while ($reader.Read()) {
$key = $reader.GetString(1)
$previousScripts.Add($key) | Out-Null
}
$reader.Close();
Write-Output "$(Get-Date) Finished querying previous scripts"
}
catch {
$exceptionMessage = $_.Exception.Message;
Write-Output …Run Code Online (Sandbox Code Playgroud) 我对以下两个简单的片段感到困惑:
#include <vector>
struct A{
int foo(int i) const {return v[i];}
std::vector<int> v;
};
int f(const A &a, int i) {
int j;
j=a.foo(i);
j=a.foo(i);
return j;
}
Run Code Online (Sandbox Code Playgroud)
它给出了汇编代码:
movsxd rax, esi
mov rcx, qword ptr [rdi]
mov eax, dword ptr [rcx + 4*rax]
ret
Run Code Online (Sandbox Code Playgroud)
和
movsxd rax, esi
mov rcx, qword ptr [rdi]
mov eax, dword ptr [rcx + 4*rax]
ret
Run Code Online (Sandbox Code Playgroud)
这使:
push rbp
push rbx
push rax
mov ebp, esi
mov rbx, rdi
call _ZNK1A3fooEi
mov rdi, rbx …Run Code Online (Sandbox Code Playgroud) pure-function ×10
d ×2
haskell ×2
applicative ×1
assembly ×1
c++ ×1
concept ×1
debug-print ×1
function ×1
inline ×1
java ×1
monads ×1
optimization ×1
powershell ×1
reactjs ×1