【Ruby Proc进阶指南】:掌握Proc的5种高阶用法,提升代码复用效率

第一章:Ruby Proc基础概念与核心特性

什么是Proc对象

在Ruby中,Proc 是一个封装了可执行代码块的对象。它允许将代码块保存为变量,并在需要时调用执行。Proc是Ruby实现闭包(Closure)的核心机制之一,能够捕获定义时的局部变量作用域。

创建与调用Proc

使用 Proc.new 或 lambda 可以创建Proc对象,两者语法相似但行为略有不同。以下是一个简单的Proc创建与调用示例:

# 创建一个Proc对象
my_proc = Proc.new { |name| puts "Hello, #{name}!" }

# 调用Proc
my_proc.call("Alice")  # 输出: Hello, Alice!

上述代码中,call 方法用于触发Proc的执行,传入的参数会传递给代码块中的形参。

Proc与Lambda的区别

尽管两者都属于Proc类实例,但在参数处理和返回行为上存在差异。以下是关键区别的对比表格:

特性ProcLambda
参数数量检查宽松,多余或缺少参数不会报错严格,参数不匹配会抛出异常
return行为从定义它的方法中直接返回仅从lambda内部返回

闭包与变量绑定

Proc具备闭包能力,可以访问并修改其定义环境中的局部变量。例如:

def make_counter
  count = 0
  Proc.new { count += 1 }
end

counter = make_counter
puts counter.call  # 输出: 1
puts counter.call  # 输出: 2

每次调用该Proc时,都会保留对 count 的引用并持续累加,体现了闭包的状态保持特性。

第二章:Proc的高阶用法详解

2.1 理解Proc对象的闭包行为与作用域捕捉

在Ruby中,`Proc`对象是闭包的实现形式之一,能够捕获其定义时所处的上下文环境,包括局部变量和方法作用域。
闭包的作用域捕捉机制
`Proc`在创建时会“冻结”当前作用域中的变量引用,允许在后续调用中访问和修改这些变量,即使该作用域已退出。

x = 10
proc_example = Proc.new { x += 1 }
x = 5
proc_example.call
puts x  # 输出: 6
上述代码中,`Proc`捕获了对变量`x`的引用而非其值。当`call`被调用时,操作的是当前外部作用域中的`x`,体现了动态作用域特性。
与lambda的区别
  • `Proc`对参数数量不敏感,多余参数被忽略,缺少则设为nil;
  • 使用return在`Proc`中会直接从外层方法返回;
  • 而lambda表现更像方法,具有严格的参数检查和局部返回行为。

2.2 使用Proc实现函数式编程中的高阶函数模式

在Ruby中,Proc对象允许将代码块封装为可传递的实体,是实现高阶函数的关键工具。通过将函数作为参数传递或返回值返回,可以构建灵活的函数式编程模式。
Proc的基本创建与调用
square = Proc.new { |x| x ** 2 }
puts square.call(5)  # 输出 25
上述代码创建了一个计算平方的Proc对象。使用call方法触发执行,参数通过块变量x接收。
作为高阶函数的参数传递
  • 高阶函数接受其他函数(Proc)作为参数
  • 常见于map、select等集合操作
def apply_twice(proc, value)
  proc.call(proc.call(value))
end

double = Proc.new { |n| n * 2 }
puts apply_twice(double, 3)  # 输出 12
该示例展示了如何将Proc作为参数传入另一个函数,并在其内部两次调用,体现了函数复合的思想。

2.3 Proc与Block、Lambda的区别与性能对比分析

核心概念辨析
Proc、Block 和 Lambda 均为 Ruby 中的可调用对象,但行为存在关键差异。Block 是临时代码块,不可独立存在;Proc 与 Lambda 则是 Proc 类实例,可保存并复用。
  • Block:通过 yield 或 &block 传入,无法单独存储
  • Proc:使用 Proc.new 创建,参数错误不严格校验
  • Lambda:使用 lambda{} 定义,参数数量严格匹配,return 表现更符合方法语义
行为差异示例
l = lambda { |x| x * 2 }
p = Proc.new { |x| x * 2 }

puts l.call(2)    # 输出 4
puts p.call(2)    # 输出 4

# 参数处理差异
puts l.call      # 抛出 ArgumentError
puts p.call      # 返回 nil,不报错
上述代码体现 Lambda 对参数严格校验,而 Proc 更宽松。
性能对比
类型创建开销调用速度适用场景
Block最低高迭代器、临时逻辑
Proc中等中需复用的灵活逻辑
Lambda较高高函数式编程、闭包

2.4 动态封装逻辑:Proc在策略模式中的实践应用

在Ruby中,Proc对象能够将代码块封装为可传递的执行单元,极大增强了策略模式的灵活性。通过将不同算法逻辑封装为Proc实例,可在运行时动态切换行为。
策略的动态注册
  • 使用Proc替代传统子类实现,减少继承层级
  • 将业务规则以闭包形式存储,提升复用性

discount_strategies = {
  regular: Proc.new { |price| price * 0.9 },
  premium: Proc.new { |price| price * 0.7 },
  vip:     Proc.new { |price| [price * 0.5, 100].max }
}
上述代码定义了多种折扣策略,每个Proc接收价格参数并返回计算结果。vip策略还结合了最低优惠门槛,体现复杂逻辑的封装能力。
运行时策略调度
通过哈希键动态调用对应Proc,实现无需条件分支的策略分发,使代码更简洁且易于扩展。

2.5 Proc的参数处理机制与调用灵活性优化技巧

Ruby中的Proc对象支持灵活的参数处理,能通过*捕获可变参数,提升调用适应性。
参数解包与默认值处理
p = Proc.new { |a, b = 2, *rest| a + b + rest.sum }
puts p.call(1)           # => 3
puts p.call(1, 3, 4, 5)  # => 13
上述代码中,b为默认参数,*rest收集多余参数。Proc在调用时对缺失参数不抛异常,而是赋值为nil或使用默认值。
参数绑定优化技巧
  • 使用lambda?判断Proc类型,区分严格参数检查行为
  • 结合arity方法动态适配传入参数数量
  • 利用curry实现柯里化,分步传递参数提升复用性

第三章:Proc在实际开发中的典型场景

3.1 利用Proc简化回调机制与事件处理逻辑

在Ruby中,Proc对象提供了强大的闭包功能,能够显著简化回调机制与事件处理的代码结构。通过将代码块封装为可传递的对象,开发者可以更灵活地定义异步响应逻辑。
事件注册与回调封装
使用Proc可以将回调逻辑集中管理,避免传统回调函数的分散定义:

on_save = Proc.new { |record| puts "Saved: #{record.name}" }
on_error = Proc.new { |err| puts "Error: #{err.message}" }

def save_record(record, success_callback, error_callback)
  begin
    record.save!
    success_callback.call(record)
  rescue => e
    error_callback.call(e)
  end
end
上述代码中,save_record接收两个Proc参数,分别处理成功与异常场景。这种方式提升了代码的可读性与复用性,同时支持动态替换回调行为。
优势对比
方式可维护性灵活性
普通方法回调低中
Proc回调高高

3.2 在Rails中使用Proc进行条件验证与配置动态化

在Rails应用中,Proc对象为条件验证和配置提供了强大的动态能力。通过将逻辑封装为可调用对象,开发者可在运行时灵活控制行为。
条件验证中的Proc应用

class User < ApplicationRecord
  validates :email, presence: true,
            if: Proc.new { |user| user.role == 'admin' }
end
上述代码中,if: 接收一个Proc对象,仅当用户角色为管理员时才验证邮箱存在性。Proc捕获user实例,实现基于状态的动态判断,避免硬编码逻辑。
配置动态化示例
  • Proc可用于初始化设置,延迟执行直到上下文明确
  • 适合处理依赖环境变量或数据库状态的配置项
  • 提升代码复用性,支持多场景共享同一验证规则

3.3 构建可复用的业务规则引擎:基于Proc的设计模式

在复杂业务系统中,将可变逻辑抽象为独立的处理单元(Proc)是提升可维护性的关键。通过定义统一的Proc接口,每个规则模块可独立注册、执行与测试。
Proc 接口设计
type Proc interface {
    Name() string
    Execute(ctx context.Context, input map[string]interface{}) (map[string]interface{}, error)
}
该接口规范了规则名称与执行方法,便于动态编排与日志追踪。参数 input 使用通用映射结构,支持灵活的数据传递。
规则注册与调度
使用注册表集中管理Proc实例:
  • 按优先级排序执行
  • 支持条件触发与链式调用
  • 提供失败回滚钩子
通过元数据标签标注规则依赖,实现自动化依赖解析与热插拔部署,显著提升业务逻辑迭代效率。

第四章:提升代码复用与设计优雅性的实战技巧

4.1 将重复逻辑抽象为Proc:减少代码冗余的工程实践

在复杂系统开发中,重复的业务逻辑不仅增加维护成本,还容易引入一致性问题。通过将高频复用的代码段封装为存储过程(Proc),可显著提升代码的可维护性与执行效率。
封装通用数据校验逻辑
例如,用户注册与信息更新均需验证邮箱格式与唯一性,可将其抽象为独立的校验存储过程:

CREATE PROC ValidateEmail(IN email_input VARCHAR(255))
BEGIN
    IF email_input NOT REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Invalid email format';
    END IF;
    
    IF EXISTS (SELECT 1 FROM users WHERE email = email_input) THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Email already exists';
    END IF;
END;
该Proc被多个业务接口调用,避免了正则表达式和查询逻辑的重复编写,统一了校验标准。
优势分析
  • 降低代码冗余,提升可读性
  • 集中维护,便于修复缺陷和扩展规则
  • 数据库层预编译,提高执行性能

4.2 结合模块与Proc实现灵活的行为注入机制

在现代系统设计中,行为注入机制是提升模块扩展性的关键。通过将功能模块与Proc(过程对象)结合,可在运行时动态注入定制逻辑。
动态行为注册
利用Proc封装可执行单元,模块在关键执行点预留钩子(Hook),支持外部Proc注册:

type Module struct {
    hooks map[string]func(interface{}) error
}

func (m *Module) RegisterHook(name string, proc func(interface{}) error) {
    m.hooks[name] = proc
}
上述代码中,RegisterHook 接收函数作为参数,实现行为解耦。参数 proc 为符合预定义签名的闭包,可在不修改核心逻辑的前提下插入校验、日志或监控逻辑。
执行流程控制
  • 模块初始化时构建Hook映射表
  • 运行时根据条件触发对应Proc
  • 支持优先级排序与异常拦截

4.3 使用Proc优化DSL设计,提升API表达力

在Ruby等支持闭包的语言中,Proc为DSL(领域特定语言)的设计提供了强大的表达能力。通过将行为封装为可传递的代码块,开发者能够构建出语义清晰、结构自然的API。
利用Proc实现延迟执行
validator = Proc.new { |value| value.is_a?(String) && !value.empty? }

def validate(name, &rule)
  rule.call(name)
end

validate("John", &validator) # => true
上述代码中,Proc将验证逻辑封装,使API调用者关注“什么校验”而非“如何校验”,提升了抽象层级。
增强API的流畅性
  • 将复杂逻辑隐藏在简洁的块语法背后
  • 支持链式调用与上下文传递(instance_eval)
  • 使配置类接口更接近自然语言描述
通过合理使用Proc,DSL不仅能减少冗余代码,还能显著提升可读性与扩展性。

4.4 多Proc组合与链式调用:构建流畅接口(Fluent Interface)

在高并发编程中,通过组合多个 Proc 并支持链式调用,可显著提升代码的可读性与可维护性。流畅接口设计模式允许开发者以自然语句的方式串联操作。
链式调用的基本结构
每个方法返回对象自身(即 this 或接收者),从而支持连续调用:

type Processor struct {
    data []int
    err  error
}

func (p *Processor) Load(data []int) *Processor {
    p.data = data
    return p
}

func (p *Processor) Validate() *Processor {
    if len(p.data) == 0 {
        p.err = fmt.Errorf("data is empty")
    }
    return p
}

func (p *Processor) Process() *Processor {
    if p.err != nil {
        return p
    }
    // 模拟处理逻辑
    for i := range p.data {
        p.data[i] *= 2
    }
    return p
}
上述代码中,Load、Validate 和 Process 均返回 *Processor,构成链式调用基础。
实际调用示例
  • 初始化处理器实例
  • 依次加载、验证并处理数据
  • 形成语义清晰的调用链
最终调用形式如下:

result := NewProcessor().Load([]int{1, 2, 3}).Validate().Process()
该模式使代码更接近自然语言表达,增强可读性与开发效率。

第五章:总结与进阶学习建议

持续构建实战项目以巩固技能
真实项目是检验技术掌握程度的最佳方式。建议从微服务架构入手,尝试使用 Go 语言构建一个具备 JWT 认证、GORM 操作数据库的 RESTful API 服务:

package main

import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "your-app/models"
)

func main() {
    r := gin.Default()
    db := models.ConnectDB() // 初始化数据库连接
    r.POST("/login", func(c *gin.Context) {
        var user models.User
        if err := c.ShouldBindJSON(&user); err != nil {
            c.JSON(400, gin.H{"error": "Invalid input"})
            return
        }
        // 验证用户逻辑(可结合 bcrypt 加密)
        token := generateJWT(user.ID)
        c.JSON(200, gin.H{"token": token})
    })
    r.Run(":8080")
}
深入理解系统设计模式
掌握常见架构模式如 CQRS、事件溯源和六边形架构,能显著提升系统可维护性。以下为微服务组件分工建议:
组件技术栈示例职责
API 网关Kong / Envoy路由、限流、认证
用户服务Go + PostgreSQL管理用户生命周期
消息队列RabbitMQ / Kafka异步解耦服务通信
制定个性化学习路径
  • 每周阅读一篇 CNCF 毕业项目的源码(如 Prometheus 或 etcd)
  • 参与开源项目提交 PR,提升代码审查与协作能力
  • 使用 Terraform 编写基础设施即代码(IaC),部署至 AWS 或阿里云环境
  • 定期复盘线上故障案例,建立个人知识库
黑猫带你学eMMC协议第4篇:eMMC概述 1 前言 声明: 本文依据eMMC JEDEC5.1协议及个人工作经验整理而成,如有错误请留言。 文章为个人辛苦整理,付费内容,禁止私自转载。 本文大约3000字,从emmc的内部结构框架、供电、总线、寄存器等各方面进行框架性的介绍,本章节内容不需要深入研究,读完本篇文章,只要能对emmc有个框架下的了解,就可以了。 2 内部结构框架 由图可以看出,emmc内部由两块组成:控制器 + 存储介质。emmc内部存储介质绝大部分为nand flash。 众所周知,我们需要存储数据到nand flash中,并 阅读详情

相关推荐

静态时序分析(STA)_深入解析Data to Data Checks的零周期挑战

本文深入解析了静态时序分析(STA)中Data to Data Checks的核心概念与零周期挑战。重点探讨了当Setup要求值超过时钟周期时,工具如何调整发射沿,并导致Hold检查的发射与捕获沿“分裂”这一反直觉现象。文章通过案例详细解读了时序报告,并提供了通过调整约束或接受多周期保持两种策略来应对这一挑战,帮助工程师正确理解和处理此类复杂时序检查。

weixin_29204205的博客 351

ruby中的Proc类的理解

这是ruby的API文档中的解释: Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables. Pro

beyond-mrzou的专栏 2103

STM32F407 CubeMX UART DMA高效解析BNO085九轴数据

本文详细介绍了如何在STM32F407平台上使用CubeMX配置UART和DMA高效解析BNO085九轴传感器数据。通过DMA循环接收机制实现低CPU占用的实时数据采集,并分享数据解析技巧、错误处理及实战调试经验,为嵌入式开发者提供完整解决方案。

o4p5q6r7s的博客 235

ruby中的&操作符,以及各种闭包、proc的调用研究

class Array def iterate!(&code) #注意这里用了&符号 self.each_with_index do |n,i| self[i] = code.call(n) end end end arr = [1,2,3,4] arr.iterate! do |n| n ** 2 en...

weixin_30784945的博客 159

ADS仿真功率放大器实例学习笔记

ADS仿真功率放大器实例学习笔记

qq_36521926的博客 1万+

【3DSlicer】基于心脏ct影像重建3d模型及导出

软件:3DSlicer4.11 基于心脏ct影像重建3d模型

Liuees的博客 1万+

12 种方式轻松实现 Ruby 调用

作者 |Gregory Witek译者 | 弯月,责编 | 王晓曼头图 | 优快云 下载自东方IC出品 | 优快云(ID:优快云news)以下为译文:最近,与同事聊天的时候,我们...

AI科技大本营 7005

【项目实战】基于STM32单片机的智能小车设计(有代码)

【1】背景意义 近些年随着国民生活水平的提升,以小车为载体的轮式机器人进入了我们的生活,尤其是在一些布线复杂困难的安全生活区和需要监控的施工作业场合都必须依赖轮式机器人的视频监控技术。因此,基于嵌入式技术的无线通信视频监控轮式机器人应运而生。由于它们与人类工作相比具有成本低廉、安全稳定的优点,目前已经在许多危险作业以及工业场合得到了广泛应用而且轮式机器人不需要像人那样采取过多的保护措施,因此轮式机...

ShawnWang1994的博客 13万+

Ruby Proc类

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和图片上传 LaTex数学公式 UML序列图和流程图 离线写博客 导入导出Markdown文件 丰富的快捷键 快捷键 加粗 Ctrl + B 斜体 Ctrl + I 引用 Ctrl

wlchn 2004

LLC谐振变换器设计实战:从工作原理到参数设计与调试

开关电源设计是电力电子领域的核心技术,其核心目标在于提升效率与功率密度。为实现这一目标,软开关技术应运而生,它通过精心控制开关器件的电压与电流波形,使其在开通或关断瞬间实现零电压或零电流切换,从而从根本上降低开关损耗。LLC谐振变换器正是这一技术的杰出代表,它通过引入谐振网络,巧妙地实现了主开关管的零电压开关和次级整流管的零电流开关。这种拓扑结构在服务器电源、通信设备及高端显示驱动等要求高效率、高功率密度的应用场景中价值显著。本文将以半桥LLC为例,深入剖析其工作模态与增益特性,并系统阐述其参数设计、仿真验

weixin_34129696的博客 561

二十八.国民技术MCU开发之UID获取与应用

在国民NT MCU中均有一个96位和128位的唯一设备标识符,其中UCID128 位, UID 为 96 位。手册中描述的作用是:通常用来做为序列号或作为密码,在编写闪存时,将此唯一标识与软件加解密算法相结合,进一步提高代码在闪存存储器内的安全性,也可用于激活带安全功能的自举程序(SecureBootloader)。UCID 和 UID,遵守国民技术芯片序列号定义,它包含芯片生产及版本相关信息。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 1677

【Ruby块编程核心技巧】:掌握5种高阶用法让你代码效率提升300%

掌握Ruby块用法,提升代码简洁性与执行效率。本文详解5种高阶应用场景,包括迭代器、回调处理、资源管理等核心技巧,助你写出更优雅的Ruby代码。实用方法全覆盖,值得收藏。

QuickProceed的博客 697

UFAST车道线检测 Ultra-Fast-Lane-Detection 从环境搭建到复现完成(一)

UFAST车道线检测 Ultra-Fast-Lane-Detection 从环境搭建到复现完成(一)

m0_46364958的博客 4345

Lightweight Charts 蜡烛图体宽度计算全解析:optimalCandlestickWidth 与 candlestickWidth 的像素级实现

本篇技术指南聚焦 Lightweight Charts 开源仓库中蜡烛图(Candlestick)实体宽度的官方计算逻辑。文档 [candlestick.md](https://link.gitcode.com/i/d99f9a50ea0c1ccbb85a2d98de712b21) 提供了两个核心函数——`optimalCandlestickWidth` 与 `candlestickWidth`,

gitblog_01122的博客 1072

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Ruby中Block、Proc和Lambda的区别(90%开发者都理解错误)

掌握Ruby块用法,彻底搞懂Block、Proc和Lambda的核心区别。解析三者在作用域、返回行为和参数处理上的不同,适用于回调、迭代和闭包场景。理解正确使用方式可提升代码健壮性,90%开发者都曾混淆的概念一文厘清,值得收藏。

CompiShoal的博客 734

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

ruby.wasm与JavaScript双向交互:10个实用技巧提升开发效率

**ruby.wasm** 是一个革命性的项目,它将完整的 Ruby 运行时编译为 WebAssembly,让开发者能够在浏览器、Node.js 和其他 WebAssembly 运行时中运行 Ruby 代码。通过 JavaScript 与 Ruby 的无缝双向交互,ruby.wasm 为前端开发、边缘计算和跨平台应用带来了全新的可能性。本文将分享 10 个实用技巧,帮助你充分利用 ruby.was

gitblog_00529的博客 602

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【Ruby性能优化新思路】:通过Lambda重构代码,提速高达40%的方法论

掌握Ruby性能优化新方法,利用Ruby Lambda 表达式重构代码逻辑,显著提升执行效率。适用于高频调用场景与函数式编程结构,减少内存开销,增强可读性。实测性能提升高达40%,值得收藏。

StepLens的博客 690

crystalruby入门指南:在Ruby中嵌入Crystal代码的终极方案,性能提升50倍

crystalruby 是一个革命性的 Ruby gem,它允许你直接在 Ruby 代码中嵌入 Crystal 代码,通过自动编译与 FFI 链接,将耗时方法替换为原生机器码版本,实测性能最高可提升 **50 倍**。本文是一份面向新手的 crystalruby 入门指南,带你从原理、安装到实战,快速掌握这一 Ruby 性能优化的终极方案。 [![crystalruby项目logo,蓝白冰晶包裹

gitblog_00062的博客 267

为什么高手都在用Ruby块?这7个实际应用场景告诉你答案

掌握Ruby块用法,提升代码优雅度与效率。本文解析7大实际应用场景,涵盖迭代处理、资源管理、回调机制等核心方法,展现块在简化逻辑和增强复用上的优势。为什么高手偏爱使用块?答案在这里,值得收藏。

BytePerch的博客 796

找不到运行按钮?Monaco Editor 在网页端展示代码执行结果的 3 条路径

你在 Monaco Editor 里写完代码,四下张望想找"运行"按钮——找不到。这不是 bug:Monaco Editor 是 VS Code 的浏览器内核,它只负责"把代码显示出来、编辑好",把执行结果摆到你面前这件事,得自己接上线。好消息是路径只有三条:诊断红线、Worker 回传、LSP 语言服务,下面按你实际看到的界面顺序过一遍。 ## 先拆掉一个误区:它不是"没有运行按钮的 IDE"

gitblog_00729的博客 981

TypeProf 入门指南:Ruby 代码类型分析的终极工具

TypeProf 是一个革命性的 Ruby 代码类型分析工具,它通过抽象解释的方式在类型级别执行 Ruby 程序。无论你是 Ruby 新手还是经验丰富的开发者,TypeProf 都能帮助你更好地理解和测试代码,提升代码质量和开发效率。这个强大的工具可以分析你的 Ruby 代码并生成类型签名,让静态类型检查成为 Ruby 开发的一部分。 ## 🚀 快速开始:5分钟掌握 TypeProf ###

gitblog_00692的博客 492

Ruby语言的函数实现

在Ruby中,方法的定义使用def关键字,后面跟上方法名和参数列表,最后用end结束。rubyendrubysay_hello # 输出: Hello, World!本文详细探讨了Ruby语言中方法的定义与调用、参数传递、返回值、作用域、重载与重写,以及与Proc和块的关系等。理解这些概念不仅可以帮助你更好地编写Ruby代码,还能够提高编程的效率和代码的可维护性。希望通过本篇文章,读者能对Ruby中的方法有更深入的理解,并在实际开发中灵活运用这些知识,以编写出高质量的代码。!

2501_90417020的博客 502

Ruby语言的箭头函数

在Ruby中,定义一个箭头函数非常简单,我们可以使用如下的语法:```ruby箭头函数作为Ruby语言中一种强大的功能,为开发者提供了更加灵活和简洁的编程体验。通过对其定义、用法的深入理解,开发者可以在项目中更有效地利用箭头函数来优化代码。虽然使用箭头函数也有其不足,但在现代软件开发中,其优势显然更为突出。因此,不论你是Ruby的初学者还是资深开发者,灵活运用箭头函数都将提升你在编程中的效率和可读性。

2501_91409228的博客 480

Ruby Next 开发者完全指南:从安装到高级配置的10个技巧

Ruby Next 是一款强大的 Ruby 代码转译工具和 polyfills 集合,让开发者能够在旧版本 Ruby 环境中使用最新的 Ruby 特性。本指南将通过 10 个实用技巧,帮助你从安装到高级配置全面掌握 Ruby Next,轻松实现跨版本 Ruby 开发。 ### 一、快速安装 Ruby Next 的 3 种方法 Ruby Next 提供多种安装方式,满足不同开发场景需求: **

gitblog_00070的博客 370

Redlock性能优化指南:如何配置retry_count和retry_delay提升锁获取效率

Redlock是一个基于Redis的Ruby分布式锁实现,下载量超过4000万次,是Ruby生态中最受欢迎的分布式锁解决方案之一。在实际生产环境中,合理配置retry_count和retry_delay参数可以显著提升分布式锁的获取效率和系统稳定性。本文将为您详细介绍如何通过优化这两个关键参数来提升Redlock的性能表现。 ## 📊 理解Redlock的重试机制 Redlock的分布式锁算

gitblog_00594的博客 640

Ruby哈希与数组的选择困境,一文讲透何时该用谁

解决Ruby数据结构选择难题,深入解析哈希与数组的适用场景。涵盖Ruby哈希用法、查找效率对比及存储逻辑差异,帮助开发者快速判断何时使用哈希或数组。掌握核心原则,提升代码性能,值得收藏。

FuncIsle的博客 783
上一篇: (Scala集合高级技巧):隐式转换与自定义集合类的设计艺术
下一篇: 5分钟彻底搞懂Ruby正则表达式,开发者必收藏
SimCompile
博客等级 码龄1年 140粉丝 2012原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值