我试图找到一个很好的来源,解释为什么global
在python(以及一般的编程)中使用被认为是不好的做法.有人可以指点我或解释一下吗?
有时,if
语句可能相当复杂或冗长,因此为了便于阅读,最好在之前提取复杂的调用if
.
例如:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
进入这个
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
(提供示例并不是那么糟糕,它仅用于说明...想象其他具有多个参数的调用等)
但是通过这种提取,我失去了短路评估(SCE).
这些术语似乎有 不同的定义,但我总是想到一个暗示另一个; 当表达式是引用透明但不纯粹时,我无法想到任何情况,反之亦然.
维基百科为这些概念维护单独的文章并说:
从参考透明度:
如果表达式中涉及的所有函数都是纯函数,则表达式是引用透明的.此外,如果丢弃它们的值并且它们的副作用无关紧要,则表达式中可以包含一些不纯的函数.
来自纯粹的表达:
构造纯表达式需要纯函数.[...]纯表达通常被称为引用透明.
我发现这些陈述令人困惑.如果副作用所谓的"非纯函数"是微不足道的,足以让不执行他们(即替换其这种函数的调用值没有实质性改变程序),它是一样的,如果它的是纯粹的第一名,不是吗?
有没有更简单的方法来理解纯表达式和引用透明的表达式之间的差异(如果有的话)?如果存在差异,则可以理解清楚地表明它的示例表达.
language-agnostic functional-programming side-effects referential-transparency purely-functional
我通常del
在我的代码中使用删除对象:
>>> array = [4, 6, 7, 'hello', 8]
>>> del(array[array.index('hello')])
>>> array
[4, 6, 7, 8]
>>>
Run Code Online (Sandbox Code Playgroud)
但我听到很多人说使用del
是unpythonic.使用del
不好的做法?
>>> array = [4, 6, 7, 'hello', 8]
>>> array[array.index('hello'):array.index('hello')+1] = ''
>>> array
[4, 6, 7, 8]
>>>
Run Code Online (Sandbox Code Playgroud)
如果没有,为什么有很多方法可以在python中完成同样的事情?一个比其他人好吗?
选项1:使用 del
>>> arr = [5, 7, 2, 3]
>>> del(arr[1])
>>> arr
[5, 2, 3]
>>>
Run Code Online (Sandbox Code Playgroud)
选项2:使用 list.remove()
>>> arr = [5, 7, 2, 3]
>>> arr.remove(7)
>>> arr
[5, 2, 3] …
Run Code Online (Sandbox Code Playgroud) 运行以下代码:
// In Java, output #####
public static void main(String[] args) {
int i = 1;
if(i == (i = 2)) {
System.out.println("@@@@@");
} else {
System.out.println("#####");
}
}
Run Code Online (Sandbox Code Playgroud)
但:
// In C, output @@@@@?I did test on Clion(GCC 7.3) and Visual Studio 2017
int main(int argc, char *argv[]) {
int i = 1;
if(i == (i = 2)) {
printf("@@@@@");
} else {
printf("#####");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
提出这个问题的动机来自以下代码:
// The code is from the JDK 11 - java.util.concurrent.atomic.AtomicInteger …
Run Code Online (Sandbox Code Playgroud) 根据维基百科的副作用条目,提出异常构成副作用.考虑一下这个简单的python函数:
def foo(arg):
if not arg:
raise ValueError('arg cannot be None')
else:
return 10
Run Code Online (Sandbox Code Playgroud)
调用它将foo(None)
始终遇到异常.相同的输入,相同的输出.它是参考透明的.为什么这不是一个纯粹的功能?
Webpack 4增加了一项新功能:它现在支持捆绑的模块中的sideEffects
标志package.json
.
在过去的30天里,我们与每个框架密切合作,以确保他们已准备好在各自的cli等支持webpack 4.即使像lodash-es这样的流行库,RxJS也支持sideEffects标志,所以通过使用他们的最新版本版本,您将看到即时捆绑尺寸减少开箱即用.
"sideEffects":big-module的package.json中的false标志表示包的模块没有副作用(评估时)并且只暴露导出.这允许像webpack这样的工具优化再出口.
虽然第二个链接显示了使用该标志的结果,但它没有清楚地解释什么构成副作用.ES6包含了此处概述的模块副作用的概念,但这与Webpack考虑的副作用有何关系.
在sideEffects
标志的上下文中,模块需要避免在sideEffects:false
没有问题的情况下使用什么,或者对话,模块需要做什么才能sideEffects:false
无问题地使用.
为了完整起见,尽管@ SeanLarkin在下面给出了可靠的答案,但我想对以下内容进行澄清:
显然,副作用意味着fp特有的东西,包括日志记录(控制台或其他地方)和抛出错误.我假设在这种情况下这些是完全可以接受的吗?
模块是否可以包含循环引用并仍然使用sideEffects: false
?
有没有办法验证或模块是否能够验证模块是否可以sideEffects: false
超越试图追踪由其误用造成的错误?
是否还有其他因素会妨碍模块的使用sideEffects: false
?
monad被描述为处理IO的haskell解决方案.我想知道是否有其他方法可以用纯函数式语言处理IO.
我在 Sonar 中发现了一条规则:
与其他中间 Stream 操作的一个关键区别是 Stream 实现可以自由地跳过调用以
peek()
达到优化目的。这可能会导致peek()
意外地仅调用 Stream 中的部分元素或不调用任何元素。
另外,Javadoc中也提到了这一点:
此方法的存在主要是为了支持调试,您希望在元素流经管道中的某个点时查看它们
什么情况下可以java.util.Stream.peek()
跳过?和调试有关系吗?
一次又一次,我读了长期effectful,但我还是无法给予的是什么意思的明确定义.我认为正确的上下文是effectful 计算,但我也看到了长期effectful 值)
我曾经认为有效的手段有副作用.但在Haskell中没有副作用(除了某种程度上IO).整个地方仍然有效的计算.
然后我读到monad用于创建有效的计算.我可以在State
Monad 的背景下理解这一点.但我没有看到Maybe
monad中有任何副作用.一般来说,在我看来,Monads包含一个类似函数的东西更容易看到产生副作用比Monads只包装一个值.
谈到Applicative
仿函数,我更加迷失.我总是看到applicative functor作为一个map
带有多个参数的函数的方法.我在这里看不到任何副作用.或者是有之间的差异effectful并用的效果?
side-effects ×10
java ×2
monads ×2
python ×2
applicative ×1
bundler ×1
c ×1
c++ ×1
haskell ×1
if-statement ×1
io ×1
java-8 ×1
java-stream ×1
javascript ×1
mutable ×1
package.json ×1
slice ×1
sonarqube ×1
webpack ×1