用 Block 重构代码的几种方法

简介: 用 Block 重构代码的几种方法

Ruby 中 block 是非常重要的,也是非常特别的一部分内容。 很多代码的重构都可以通过 code block 得以一种优雅的方式实现。 根据《Ruby 最佳实践》中的内容,我简单做一些小结。

首先,最常见的就是用于遍历。

(1..5).to_a.map { |i| i * 2 }
class SortedList
  def initialize
    @data = []
  end
  def <<(element)
    (@data << element).sort!
  end
  def each
    @data.each { |e| yield(e) }
  end
end

其次,用于在方法的预处理和后处理操作中插入代码

File.open("some.txt") { |f| f << "some words" }

有时也用于临时提升变量的可见范围(scope)(在元编程中比较常见)

"This is a string".instance_eval do
  "O hai, can has reverse? #{ revers }. kthxbye"
end
#=> "O hai, can has reverse? gnirts a si sihT. kthsbye"

最后,就是作为模板

>> foo = Hash.new { |h, k| h[k] = [] }
=> {}
>> foo[:bar]
=> []
>> foo[:bar] << 1 << 2 << 3
=> [1, 2, 3]

用 Block 重构代码的几个范例

用 block 来重构 Pre 和 Post 处理过程

require "socket"
class Client
  def initialize(ip = "127.0.0.1", port = 3333)
    @ip, @port = ip, port
  end
  def send_message(msg)
    socket = TCPSocket.new(@ip, @port)
    socket.puts(msg)
    response = socket.gets
  ensure
    socket.close if socket
  end
  def receive_message
    socket = TCPSocket.new(@ip, @port)
    response = socket.gets
  ensure
    socket.close if socket
  end
end

这个代码明显不符合 DRY 的风格,所以利用 block 来重构一下:

require "socket"
class Client
  def initialize(ip = "127.0.0.1", port = 3333)
    @ip, @port = ip, port
  end
  def send_message(msg)
    connection do |socket|
      socket.puts(msg)
      socket.gets
    end
  end
  def receive_message
   connection { |socket| socket.gets }
  end
  private
  def connetcion
    socket = TCPSocket.new(@ip, @port)
    yield(socket)
  ensure
    socket.close if socket
  end
end
if __FILE__ == $0
  client = Client.new
  ["Hello", "My name is Greg", "Goodbye"].each do |msg|
    response = client.send_message(msg)
    puts response
  end
end
#输出以下内容
#Hello from server at Wed Jul 23 16:15:37 ...
#Nice to meet you Greg!
#Goodbye from server at Wed Jul 32 ...

以上代码明显简洁了很多

用于动态回调

require 'socket'
class Server
  def initialize(port = 3333)
    @server = TCPServer.new("127.0.0.1", port)
    @handlers = {}
  end
  def handle(pattern, &block)
   @handlers[pattern] = block
  end
  def run
    while session = @server.accept
      msg = session.gets
      match = nil
      @handlers.each do |pattern, block|
        if match = msg.match(pattern)
          break session.puts(block.call(match))
        end
        unless match
          session.puts "Server received unknown message: #{msg}"
        end
      end
    end
  end
end
if __FILE__ == $0
  server = Server.new
  server.handle(/hello/i){ "Helllo from server at #{Time.now}" }
  server.handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
  server.handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
  server.run
end

用于简化接口

server = Server.new
server.handle(/hello/i){ "Helllo from server at #{Time.now}" }
server.handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
server.handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
server.run
#这段代码可以简化为以下版本
Server.run do
  handle(/hello/i){ "Helllo from server at #{Time.now}" }
  handle(/goodbye/i){ "Goodbye from server at #{Time.now}" }
  handle(/name is (\w+)/){ |m| "Nice to meet you #{m[1]}!" }
end
#class Server修改如下
class Server
  #other methods same as before
  #声明为类方法
  def self.run(port=3333, &block)
    server = Server.new(port)
    #使用instance_eval和&block来重构代码
    server.instance_eval(&block)
    server.run
  end
end


相关文章
|
算法
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
902 0
|
12月前
|
存储 IDE 持续交付
《深度剖析:PEP8规范如何成就Python代码的高阶形态》
PEP8是Python社区的代码风格指南,涵盖代码布局、命名规范、注释与文档字符串、导入语句等多个方面。它提倡4个空格缩进、清晰命名(如函数用小写字母加下划线,类名用驼峰法)和合理注释,提升代码可读性与可维护性。同时,工具如Flake8和Pylint可检查代码是否符合PEP8规范,编辑器和CI流程的集成进一步保障了代码质量。遵循PEP8不仅使代码更美观,还为团队协作和项目稳定奠定了基础。
351 0
|
运维 监控 数据可视化
Hyper-V的哪些性能?使其成为企业构建云平台和虚拟化环境的首选
Hyper-V凭借高效性、灵活性、高可用性及管理简便性等优势,成为企业构建云平台和虚拟化环境的首选。其微内核架构、硬件辅助虚拟化技术和动态内存管理提升了性能与资源利用率;支持多操作系统和硬件平台,具备故障转移、实时迁移功能,确保业务连续性;提供可视化管理工具和PowerShell脚本自动化,简化管理流程;与Windows Server及Azure无缝集成,降低硬件、运维和能源成本。
|
机器学习/深度学习 存储 人工智能
【AI系统】昇思MindSpore并行
本文介绍昇思MindSpore的并行训练技术,包括张量重排布、自动微分等,旨在简化并行策略搜索,提高大规模模型训练效率。文章探讨了大模型带来的挑战及现有框架的局限性,详细说明了MindSpore如何通过技术创新解决这些问题,实现高效的大模型训练。
429 20
【AI系统】昇思MindSpore并行
|
存储 算法 数据处理
Pandas高级数据处理:数据加密与解密
在数字化时代,数据安全至关重要。Pandas作为Python的强大数据分析库,结合`cryptography`等加密库,可实现数据的高效加密与解密。本文介绍如何使用Pandas进行数据加密,涵盖对称加密、非对称加密及哈希算法,并提供常见问题及解决方案,确保敏感信息的安全性。通过示例代码演示加密流程,帮助读者掌握数据加密技术,提升数据安全性。
326 1
|
数据采集 数据可视化 索引
Pandas数据应用:股票数据分析
本文介绍了如何使用Pandas库进行股票数据分析。首先,通过pip安装并导入Pandas库。接着,从本地CSV文件读取股票数据,并解决常见的解析错误。然后,利用head()、info()等函数查看数据基本信息,进行数据清洗,处理缺失值和重复数据。再者,结合Matplotlib和Seaborn进行数据可视化,绘制收盘价折线图。最后,进行时间序列分析,设置日期索引、重采样和计算移动平均线。通过这些步骤,帮助读者掌握Pandas在股票数据分析中的应用。
860 5
|
机器学习/深度学习 人工智能 自然语言处理
《深度剖析:人工智能与元宇宙构建的底层技术框架》
在科技飞速发展的当下,人工智能与元宇宙成为备受瞩目的前沿领域。人工智能的底层技术包括机器学习、深度学习和自然语言处理,赋予机器学习能力、图像识别和语言理解功能。元宇宙则依赖区块链、虚拟现实(VR/AR/MR)、数字孪生及高速网络等技术,构建去中心化、沉浸式和交互性强的虚拟世界。两者融合促进内容创作与用户体验提升,预示未来社会和经济发展的新方向。
339 0
|
存储 人工智能 开发者
三文带你轻松上手鸿蒙的AI语音02-声音文件转文本
三文带你轻松上手鸿蒙的AI语音02-声音文件转文本
525 0
三文带你轻松上手鸿蒙的AI语音02-声音文件转文本
|
机器学习/深度学习 算法 Python
群智能算法:深入解读人工水母算法:原理、实现与应用
近年来,受自然界生物行为启发的优化算法备受关注。人工水母算法(AJSA)模拟水母在海洋中寻找食物的行为,是一种新颖的优化技术。本文详细解读其原理及实现步骤,并提供代码示例,帮助读者理解这一算法。在多模态、非线性优化问题中,AJSA表现出色,具有广泛应用前景。
|
机器学习/深度学习 人工智能 自然语言处理
算法金 | 一文看懂人工智能、机器学习、深度学习是什么、有什么区别!
**摘要:** 了解AI、ML和DL的旅程。AI是模拟人类智能的科学,ML是其分支,让机器从数据中学习。DL是ML的深化,利用多层神经网络处理复杂数据。AI应用广泛,包括医疗诊断、金融服务、自动驾驶等。ML助力个性化推荐和疾病预测。DL推动计算机视觉和自然语言处理的进步。从基础到实践,这些技术正改变我们的生活。想要深入学习,可参考《人工智能:一种现代的方法》和《深度学习》。一起探索智能的乐趣!
770 1
算法金 | 一文看懂人工智能、机器学习、深度学习是什么、有什么区别!