首页 > 编程语言 >函数式编程之pipeline——很酷有没有

函数式编程之pipeline——很酷有没有

时间:2023-08-03 21:02:12浏览次数:39  
标签:pipeline return nums 编程 很酷 Number num def

Pipeline

pipeline 管道借鉴于Unix Shell的管道操作——把若干个命令串起来,前面命令的输出成为后面命令的输入,如此完成一个流式计算。(注:管道绝对是一个伟大的发明,他的设哲学就是KISS – 让每个功能就做一件事,并把这件事做到极致,软件或程序的拼装会变得更为简单和直观。这个设计理念影响非常深远,包括今天的Web Service,云计算,以及大数据的流式计算等等)

比如,我们如下的shell命令:

ps auwwx | awk '{print $2}' | sort -n | xargs echo

如果我们抽象成函数式的语言,就像下面这样:

xargs(  echo, sort(n, awk('print $2', ps(auwwx)))  )

也可以类似下面这个样子:

pids = for_each(result, [ps_auwwx, awk_p2, sort_n, xargs_echo])

好了,让我们来看看函数式编程的Pipeline怎么玩?

我们先来看一个如下的程序,这个程序的process()有三个步骤:

1)找出偶数。
2)乘以3
3)转成字符串返回

def process(num):
# filter out non-evens
if num % 2 != 0:
return
num = num * 3
num = 'The Number: %s' % num
return num
 
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
for num in nums:
print process(num)
 
# 输出:
# None
# The Number: 6
# None
# The Number: 12
# None
# The Number: 18
# None
# The Number: 24
# None
# The Number: 30

我们可以看到,输出的并不够完美,另外,代码阅读上如果没有注释,你也会比较晕。下面,我们来看看函数式的pipeline(第一种方式)应该怎么写?

def even_filter(nums):
for num in nums:
if num % 2 == 0:
yield num
def multiply_by_three(nums):
for num in nums:
yield num * 3
def convert_to_string(nums):
for num in nums:
yield 'The Number: %s' % num
 
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pipeline = convert_to_string(multiply_by_three(even_filter(nums)))
for num in pipeline:
print num
# 输出:
# The Number: 6
# The Number: 12
# The Number: 18
# The Number: 24
# The Number: 30

我们动用了Python的关键字 yield,这个关键字主要是返回一个Generator,yield 是一个类似 return 的关键字,只是这个函数返回的是个Generator-生成器。所谓生成器的意思是,yield返回的是一个可迭代的对象,并没有真正的执行函数。也就是说,只有其返回的迭代对象被真正迭代时,yield函数才会正真的运行,运行到yield语句时就会停住,然后等下一次的迭代。(这个是个比较诡异的关键字)这就是lazy evluation。

好了,根据前面的原则——“使用Map & Reduce,不要使用循环”,那我们用比较纯朴的Map & Reduce吧。

def even_filter(nums):
return filter(lambda x: x%2==0, nums)
 
def multiply_by_three(nums):
return map(lambda x: x*3, nums)
 
def convert_to_string(nums):
return map(lambda x: 'The Number: %s' % x,  nums)
 
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pipeline = convert_to_string(
multiply_by_three(
even_filter(nums)
)
)
for num in pipeline:
print num

但是他们的代码需要嵌套使用函数,这个有点不爽,如果我们能像下面这个样子就好了(第二种方式)。

pipeline_func(nums, [even_filter,
multiply_by_three,
convert_to_string])

那么,pipeline_func 实现如下:

def pipeline_func(data, fns):
return reduce(lambda a, x: x(a),
fns,
data)

好了,在读过这么多的程序后,你可以回头看一下这篇文章的开头对函数式编程的描述,可能你就更有感觉了。

最后,我希望这篇浅显易懂的文章能让你感受到函数式编程的思想,就像OO编程,泛型编程,过程式编程一样,我们不用太纠结是不是我们的程序就是OO,就是functional的,我们重要的品味其中的味道

参考

补充:评论中redraiment这个评论大家也可以读一读。

感谢谢网友S142857 提供的shell风格的python pipeline:

class Pipe(object):
def __init__(self, func):
self.func = func
 
def __ror__(self, other):
def generator():
for obj in other:
if obj is not None:
yield self.func(obj)
return generator()
 
@Pipe
def even_filter(num):
return num if num % 2 == 0 else None
 
@Pipe
def multiply_by_three(num):
return num*3
 
@Pipe
def convert_to_string(num):
return 'The Number: %s' % num
 
@Pipe
def echo(item):
print item
return item
 
def force(sqs):
for item in sqs: pass
 
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
force(nums | even_filter | multiply_by_three | convert_to_string | echo)

标签:pipeline,return,nums,编程,很酷,Number,num,def
From: https://blog.51cto.com/u_11908275/6953249

相关文章

  • linux编程
    1.读取文件流程:1.打开文件2.读/写文件3.关闭文件2.阻塞和非阻塞是文件的一种属性,只有设备文件和网络文件才有的特性3.fcntl(fd1,F_DUPFD,0)//0被占用,fcntl使用文件描述符表中可用的最小文件描述符4.fcntl(fd1,F_DUPFD,7)//7被占用,fcntl使用文件描述符表中可......
  • Linux环境编程day01--库与环境变量
    UNIX系统简介:1970年于美国贝尔实验室,作者肯.汤普逊和丹尼斯.里奇UNIX是最早的多用户、多任务、支持多种CPU架构,高稳定性、高可靠性、高安全性既能构建大型关键型业务系统的服务器(银行、电信公司等),也能支持移动嵌入式设备Minix是一种开源的基于微内核架构的类UNIX计算机操作......
  • Linux环境编程--功能函数编写1
    Linux系统编程实例11.实现一个计算文件大小的函数方法1(标准IO):函数使用:intfseek(FILE*stream,longoffset,intwhence);返回值:成功0失败-1longintftell(FILE*stream);返回值:返回位置标识符的当前值。如果发生错误,则返回-1Llongfile_size(constchar*path){......
  • 花式涵数编程
        1美人心计今日向大家介绍后花园中的3位美人,分别是命令氏、面向对象氏、函数氏。命令氏,妃,贤妻良母,夫唱妇随,和她在一起四字可形容,简单粗暴;面向对象氏,嫔,聪明伶俐,足智多谋,心眼一个接着一个,省了我不少事情;函数氏,贵人,零零后,八面玲珑,火星语乱飞,女孩的心思你别猜。她们国色天香......
  • 【测试】SAS 编程技巧 - PROC SQL(二)
    上一节中,我们介绍了如何使用SQL创建、删除数据集、修改数据集结构,以及如何新增、删除和更新数据集的观测,所涉及到的内容都是对数据集的增、删、改的操作,从本节开始,我们将对SQL中最常见,也最灵活的查询操作进行详细的介绍。查询语句SQL的查询操作是通过SELECT语句实现的。S......
  • 【测试】SAS 编程技巧 - PROC SQL(一)
    SQL全称StrucuredQueryLanguage,即结构化查询语言,广泛应用于关系型数据库中。SASBase使用PROCSQL提供了对SQL的实现。PROCSQL过程可以帮助我们完成以下任务:创建数据集、视图和索引删除数据集、视图和索引修改数据集的结构更新数据集的观测从数据集或视图中获取......
  • 深入浅出RxJava (四:在Android中使用响应式编程)
    [url=http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/]原文链接[/url]在第1,2,3篇中,我大概介绍了RxJava是怎么使用的。下面我会介绍如何在Android中使用RxJava.RxAndroidRxAndroid是RxJava的一个针对Android平台的扩展。它包含了一些能够简化And......
  • SAS 编程技巧 - PROC SQL(四)
    上一节,我们介绍了使用SELECT语句对变量进行查询,这一节我们继续介绍SELECT的简单查询操作。常量常量包括数值常量和字符串常量,有时候也被称为字面量(literal)。procsqlnoprint;createtableADSLasselect"TEST-CLINICAL-TRIAL-2023-0012"asST......
  • 面向对象编程基础
    欢迎来到C#语言入门指南的第二篇博客!在前一篇博客中,我们了解了C#语言的基本概念和历史,并成功编写了您的第一个C#程序。今天,我们将深入探讨面向对象编程(Object-OrientedProgramming,OOP)的基础知识。OOP是一种常用的编程范式,它将数据和操作数据的方法组织成对象,以便更好地模拟现实世......
  • Java编程-依据类图与流程图实现对应接口
    类图依据与流程图依据封装常见的HTTP状态码RegisterController接口register(Stringname,Stringpwd)login(Stringname,Stringpwd)NovelController接口addNovel()asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfNovelContentController接口asdfasdfasdfasdfasdf......