gpt4 book ai didi

javascript - JS 回调 : continuation-passing or candy factory style?

转载 作者:行者123 更新时间:2023-11-30 20:10:19 25 4
gpt4 key购买 nike

在编程风格类(class)中,我们被要求以“持续传递风格”和“糖果工厂风格”两种方式实现一些代码。

我们正在阅读的书是 Cristina Videira Lopes 的“Exercises in programming styles”(第 5 章和第 8 章)。

我们被要求用另一种语言实现书中的示例代码(书中是Python,现在我使用Javascript)。

为了理解我的问题,我将向您展示书中显示的两个主要区别:

糖果工厂风格

#!/usr/bin/env python
read_file(path_to_file):
"""
Takes a path to a file and returns the entire contents of the
file as a string
"""
with open(path_to_file) as f:
data = f.read()
return data


def filter_chars_and_normalize(str_data):
...

.
.
.

print_all(sort(frequencies(remove_stop_words(scan(
filter_chars_and_normalize(read_file(sys.argv[1]))))))[0:25])

延续传递风格

#!/usr/bin/env python

def read_file(path_to_file, func):
with open(path_to_file) as f:
data = f.read()
func(data, normalize)


def filter_chars(str_data, func):
pattern = re.compile(’[\W_]+’)
func(pattern.sub(’ ’, str_data), scan)


.
.
.


read_file(sys.argv[1], filter_chars)

Javascript

const fs = require('fs');


var myArgs = process.argv.slice(2);

function read_file(path_to_file,callback){
fs.readFile(path_to_file, "utf-8",(err, data) => {
if (err) throw err;
callback(data);
});
}

function string_to_lower(str_data,callback){
var data = str_data.toLowerCase()
callback(data)
}

.
.
.

function TermFrequency(){
read_file(myArgs[0],function(result){
string_to_lower(result, function(result2){
remove_non_alphanumeric(result2,function(result3){
remove_stop_words(result3,function(result4){
frequencies(result4,function(result5,result6){
sort(result5,result6,function(result7,result8){
write_out(result7,result8)
})
})
})
})
})
})
}

根据我的理解以及书中的示例,上面用 Javascript 编写的内容是 Continuation 传递,因为函数作为参数传递。但与此同时,为了调用主函数,您使用与糖果工厂相同的“管道式”调用。

上面用JS写的代码怎么可能实现糖果工厂的风格呢?该代码(基于回调)是糖果工厂还是延续传递风格?如何在不使用回调的情况下编写上面的代码,同时信任 JS?

最佳答案

我认为您混淆了两件事。糖果风格通常被称为功能组合。这就是一个函数的输出是下一个函数的输入的地方。

f(g(h(1)))

h(1) 输出一个值,这是 g 的输入,g 输出一个值,是 f 的输入。

这与 Javascript 中用于异步操作的回调样式不同。

f(1,g)

其中 f 获取一个值,对其进行处理并在稍后调用 g

在 JavaScript 中,您通常需要处理异步操作,但在这些情况下您只需要回调(延续)。像您的 stringToLower 这样的函数只需要返回数据。

function string_to_lower (str) {
return str.toLowerCase();
}

如果您要调整代码以遵循这些规则,那么您可以做一些更熟悉的事情:

function TermFrequency(){
read_file(myArgs[0],function(result){
write_out( sort(frequencies(remove_stop_words(remove_non_alphanumeric(string_to_lower(result))))));
}
}

知道这是组合,我们可以使用另一个函数来进一步简化它。

function compose (...fns) {
return function (value) {
fns.reduce(function (result, fn) {
return fn(result);
}, value);
}
}

我们可以这样使用它:

const processFile = compose(
string_to_lower,
remove_non_alphanumeric,
remove_stop_words,
frequencies,
sort,
write_out,
);

function TermFrequency(){
read_file(myArgs[0], processFile);
}

现在这可能看起来很陌生,但让我们来看看它。函数 compose 采用名为 fns 的参数列表。 ...(其余运算符)只接受单独的参数并将它们放入数组中。您会注意到 compose 函数返回另一个函数。所以 compose(omg) 会返回另一个等待 value 的函数。当您提供该值时,该函数将停止运行。我们用函数列表调用 compose,它返回一个等待值的函数。我们将该函数分配给 const processFile。然后我们执行异步操作并将 processFile 设置为回调。回调(我们的 compose 函数)接收它正在等待的值,然后同步进行所有处理。

希望这能解决一些问题。我还建议您研究 promises,这样您就不必处理回调。

JavaScript 很有趣,因为它天生就是一种异步语言。另一方面,Python 不是。这意味着在 Python 中您可以同时使用这两种样式,但在 Javascript 中有时您必须同时使用这两种样式。

另外,请记住,在 JavaScript 中,有回调,我们用它来构建 promise ,我们用它来构建 Async/Await。了解回调流程对于能够更有效地使用更高级别的工具至关重要。

关于javascript - JS 回调 : continuation-passing or candy factory style?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52480246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com