全局变量的值和类型随时都会发生变化。 这使编译器难以优化使用全局变量的代码。 变量应该是局部的,或者尽可能作为参数传递给函数。
Julia 推荐多写函数,但当最里面/最底层的函数需要一个参数时,所有用到这个函数的函数就都得加上这个参数。
如果是常量还好,const
一下当作全局变量影响也不大。如果是个需要经常更新的变量该怎么搞呢?而且这个变量要从头用到尾。是不是只能改算法了。
我现在这样写:cycle_var = f(a, b, c, cycle_var)
。然后加上最上面一条,最后代码里全是这样的语句。
举个栗子:
请勿吐槽例子本身 (不要偏题了
- “怎么不先编译然后
ccall
?” —— 这不是懒嘛,支持全平台的二进制依赖多麻烦,我还想随手去 github 上骗 star。没依赖,直接 copy 就能用多爽。
既然要编译,不如上 libpng
一把梭。
- “julia 不擅长 I/O;不是用来干这个的” —— 新到的锤子,看啥都是钉子。
JuliaOS 我看迟早的事
- “crc 部分怎么不用 base/crc 库里的” —— 会有的。这不是刚能跑通就来吐槽了么
原项目
- svpng/svpng.inc at master · miloyip/svpng
这个项目就这一个 c 文件。
- 极简的 PNG 编码函数 svpng() - 知乎
这个项目是用来干嘛的
强行改写完
点进去就能看见满屏的 c = f(io, ..., c)
, 就很难受。
目前我想到的能部分缓解的办法:
- 学原项目,用宏定义/元编程,自动把要用的全局变量加到函数的参数里
- 将函数继续拆分,把算 crc 的部分分出来。但只能缓解部分,参数
io
还是没辙。
- 弃疗,全局变量好。(x)
Roger
2
全局变量写成带有副作用的函数,例如
function foo()
push!(io, blabla)
end
改写为
function foo(io::IO)
push!(io, blabla)
end
然后在某个入口提供这个变量。所有全局变量应该都可以这么改写。
1 个赞
对啊,我现在就是这么改的,然后因为最底层的那个函数用了 write(io, xxx)
之后所有的函数就都带 io
这个参数了,调用时也得写成 f(io, xxx)
。
你去看强行改写完的 svPNG.jl
, ctrl+F
搜一下 io
, 再搜一下 c
(看函数的参数与返回值) 真的是满屏都是,感觉全局变量从污染代码变成污染眼睛了。
主要是中间那些函数带 io
这个参数就只是为了把它传下去,感觉我多打了很多字。不是很习惯,应该还能抢救一下。
那些 function-like macro 一般就直接改写成closure就行。
function svpng(fp, unsigned w ...)
SVPNG_PUT(u) = fputc(u, fp)
end
不喜欢nested function也可以用functor.
它这种 header-only 的库,用 BinaryBuilder.jl 10分钟(在提前下好shards的情况下)就能完成7个平台,36个编译器版本的支持。
1 个赞
忘了还有闭包可以用
closure + nested function 看起来还不错
Hi
I am new here. I lived in HK for 7 years and now in Manila Hope I can contribute and learn
Another way to use global variables is to make it a reference like:
const param = Ref{Float64}()
Then you can reference this in your functions like:
function f(x::Float64)
global param[] += x
end
The thing to remember is you need to use the variable with bracks []
to reference it.
Hope this helps.
4 个赞