Ruby Blocks & Closures

Topics
Blocks
What is a block?
How does a block look like?
How does a block get passed and executed?
Proc object
& (Ampersand) operator
lambda
Where do blocks get used?
Closure
What is a closure?


What is a block?
什么是Block
Blocks are basically nameless functions.
Blocks是基本的匿名函数。
You can think of it as a nameless chunk of code.
你可以认为它是一个匿名代码块。
You can pass a nameless function to another function (I will it target function in this presentation), and then that target function can invoke the passed-in nameless function
你可以用匿名函数和另一个函数相联系,然后目标函数就能调用这个匿名函数。
For example, a target function could perform iteration by passing one item at a time to the nameless function.
例如,目标函数可以执行迭代通过匿名函数。

How to Represent a Block?
怎样书写Block
A block can be represented in two different formats - these two formats are functionally equivalent
一个block有两种描述方式 - 这两种方式作用一样
  1. puts "----First format of code block containing code fragment between { and }"
  2. [1, 2, 3].each { |n| puts "Number #{n}" }
  3. puts "----Second format of code block containing code fragment between do and end"
  4. [1, 2, 3].each do |n|
  5.   puts "Number #{n}"
  6. end
How a block is passed & executed
block怎样编译,执行
When a method is invoked, a block can be passed (attached)
当一个方法被调用时,block被编译
The yield() method in the invoked method (target function) executes the passed block
  1. puts "----Define MyClass which invokes yield"
  2. class MyClass
  3.   def command()
  4.     # yield will execute the attached block to the method
  5.     yield() 
  6.   end        
  7. end
  8. puts "----Create object instance of MyClass"
  9. m = MyClass.new
  10. puts "----Call command method of the MyClass passing a block"
  11. m.command {puts "Hello World!"}
How a block receive arguments
block如何接收参数
A block can receive arguments - they are represented as comma-separated list at the beginning of the block, enclosed in pipe characters:
block能接收参数 - 参数用逗号隔开,并加上特殊字符:
  1. puts "----Define MyClass which invokes yield"
  2. class MyClass
  3.   def command1()
  4.     # yield will execute the supplied block
  5.     yield(Time.now) 
  6.   end        
  7. end
  8. puts "----Create an object instance of MyClass"
  9. m = MyClass.new
  10. puts "----Call command1 method of the MyClass"
  11. m.command1() {|x| puts "Current time is #{x}"}
A block can receive multiple arguments:
block能够接收复杂参数:
  1. puts "---Define a method called testyield"
  2. def testyield
  3.   yield(1000, "Sang Shin")
  4.   yield("Current time is"Time.now)
  5. end
  6. puts "----Call testyield method"
  7. testyield { |arg1, arg2| puts "#{arg1} #{arg2}" }


Proc Objects
What is a Proc object?
Proc objects (Procs) are blocks of code that have been converted to “callable” objects.
Proc对象是可调用的block代码块。
Proc objects are considered as first-class objects in Ruby language because they can be:
Proc对象被认识是Ruby中的第一类对象 :
Created during runtime
运行期创建
Stored in data structures (saved in a variable)
在数据结构里储存
Passed as arguments to other functions
能传递参数到其他函数
Returned as the value of other functions.
能给其他函数返回值。

How To Create a Proc Object?
怎么创建一个Proc对象?
Use new keyword of Proc class passing a block
  1. puts "----Create a Proc object and call it"
  2. say_hi = Proc.new { puts "Hello Sydney" }
  3. say_hi.call
  4. puts "----Create another Proc object and call it"
  5. Proc.new { puts "Hello Boston"}.call
How to execute a block of a Proc Object?
如何运行一个Proc对象?
Use call method of the Proc object
调用call方法

How to pass a Proc object as an argument?
如何传递一个Proc对象作为一个参数?
Pass it just like any other Ruby object - hence the reason why Proc is a first-class object
可以像传递其它Ruby对象一样传递它,因为Proc是第一类对象
  1. puts "----Create a Proc object"
  2. my_proc = Proc.new {|x| puts x}
  3. puts "----Define a method that receives Proc object as an argument"
  4. def foo (proc_param, b)
  5.   proc_param.call(b)
  6. end
  7.  
  8. puts "----Call a method that passes a Proc object as an arugment"
  9. foo(my_proc, 'Sang Shin')
How to pass Arguments to the block(represented by the Proc object)?
如何传递参数给一个block
Pass arguments in a call method of the proc object
用call方法传递
  1. puts "----Create a Proc object"
  2. my_proc = Proc.new {|x| puts x}
  3. puts "----Define a method that receives Proc object as an argument"
  4. def foo (proc_param, b)
  5.   proc_param.call(b)
  6. end
  7.  
  8. puts "----Call a method that passes a Proc object as an arugment"
  9. foo(my_proc, 'Sang Shin')
How to Use a Proc object as a Return Value?
怎样用一个Proc对象当作返回值?
Just like any other Ruby object
  1. puts "----Define a method that returns Proc object as a return value"
  2. def gen_times(factor)     
  3.     Proc.new {|n| n*factor }   
  4. end
  5. puts "----Assign Proc object to local variables"
  6. times3 = gen_times(3)   
  7. puts "----Execute the code block passing a parameter"
  8. puts times3.call(3)           

Proc Object works as a Closure
Proc objects (Procs) 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.
Proc对象是有一组本地变量约束的代码块。
  1. def gen_times(factor)
  2.    return Proc.new {|n| n*factor }  # factor is local variable in a block
  3.  end
  4.  times3 = gen_times(3)               # Block has factor variable set to 3
  5.  times5 = gen_times(5)               # Block has factor variable set to 5
  6.  times3.call(12)                           #=> 36 because 12 * 3 (factor) = 36
  7.  times5.call(5)                             #=> 25 because 5 * 5 (factor) = 25
  8.  times3.call(times5.call(4))          #=> 60 because (4 * 5  )  * 3 (factor) = 60
lambda and Proc
lambda is equivalent to Proc.new - the following three statements are considered equivalent
lambda和Proc.new等价
  1. say_hi = Proc.new { puts "Hello Sydney" }
  2. say_hi = lambda { puts "Hello Sydney" }
  3. say_hi = proc { puts "Hello Sydney" }
There are a couple of differences, however
Difference #1 between lambda and Proc
第一点不同
Argument checking: A Proc object created from using lambda checks the number of arguments passed and if they do not match, throws ArgumentError exception
参数检查:lambda会进行参数检查,不匹配就抛出ArgumentError异常
  1. puts "----Create Proc object using lambda"
  2. lamb = lambda {|x, y| puts x + y}
  3. puts "----Create Proc object using Proc.new"
  4. pnew = Proc.new {|x, y| puts x + y}
  5. puts "----Send 3 arguments, should work"
  6. pnew.call(2, 4, 11)
  7. puts "----Send 3 arguments, throws an ArgumentError"
  8. lamb.call(2, 4, 11)
lambda and Proc Difference 2
第二点不同
How return is handled from the Proc
如何处理返回值
A return from Proc.new returns from the enclosing method (acting just like a return from a block).
Proc.new的返回值来自封闭的方,返回后跳出方法
A return from lambda acts more conventionally, returning to its caller.
lambda的返回值返回给调用者
  1. def foo
  2.   f = Proc.new { return "return from foo from inside proc" }
  3.   f.call # control leaves foo here
  4.   return "return from foo" 
  5. end
  6. def bar
  7.   f = lambda { return "return from lambda" }
  8.   f.call # control does not leave bar here
  9.   return "return from bar" 
  10. end
  11. puts foo # prints "return from foo from inside proc" 
  12. puts bar # prints "return from bar" 
& (Ampersand) Operator
How & (Ampersand) is used?
&符号如何使用?
The ampersand operator can be used to explicitly convert between blocks and Procs
&操作符用于blocks和Procs的转换
Conversion from a block to a Proc
block到Procs的转换
If an ampersand (&) is prepended to the last argument in the argument list of a method, the block attached to this method is converted to a Proc object and gets assigned to that last argument.

Conversion from a Proc to a block
Another use of the ampersand is the other-way conversion - converting a Proc into a block. This is very useful because many of Ruby’s great built-ins, and especially the iterators, expect to receive a block as an argument, and sometimes it’s much more convenient to pass them a Proc.
The method receives a block as a Proc object
  1. puts "----The attached block is passed as the last argument in the form of Proc object"
  2. def my_method_ampersand(a, &f)
  3.   # the block can be accessed through f
  4.   f.call(a)
  5.     
  6.   # but yield also works !
  7.   yield(a)
  8. end
  9.  
  10. puts "----Call a method with a block"
  11. my_method_ampersand("Korea") {|x| puts x}
Pass a Proc with & preceded
  1. puts "----Create a Proc object"
  2. say_hi = Proc.new { |x| puts "#{x} Hello Korea" }
  3. puts "----Define a method which expects a block NOT Proc object"
  4. def do_it_with_block
  5.   if block_given?
  6.     yield(1)
  7.   end
  8. end
  9. puts "----Call do_it_with_block method which expects a block, convert Proc object to a block"
  10. do_it_with_block(&say_hi)
Where Do Blocks Get Used?
Blocks Usage Examples
Iteration
[1, 2, 3].each {|item| puts item}
Resource management
file_contents = open(file_name) { |f| f.read }
Callbacks
widget.on_button_press do
puts “Button is pressed”
end


What is a Ruby Closure?
In Ruby, a Proc object behaves as a Closure
A Proc object maintains all the context in which the block was defined: the value of self, and the methods, variables, and constants in scope. This context is called scope information
A block of the Proc object can still use all original scope information such as the variables even if the environment in which it was defined would otherwise have disappeared. 
Ruby Closure Example
  1. # Define a method that returns a Proc object
  2. def ntimes(a_thing)
  3.   return proc { |n| a_thing * n }
  4. end
  5. # The a_thing is set to value 23 in a block.  
  6. p1 = ntimes(23)
  7. # Note that ntimes() method has returned.  The block still
  8. # has access to a_thing variable.
  9. # Now execute the block.  Note that the a_thing is still set to
  10. # 23 and the code in the block can access it, so the results is set 69 and 92
  11. puts p1.call(3)     #   69
  12. puts p1.call(4)     #   92

【重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: 本资源原本已设置为“0积分下载”,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,自动将部分资源的积分调整为非0数值(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。强烈建议:仅在页面显示为0积分时进行下载。 另外,本资源描述中并未直接提供具体的下载地址或外部链接,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!
源码链接: https://pan.quark.cn/s/064420f76eb8 ### A2L文件制作教程与规范 ### #### 一、引言 在汽车电子领域,A2L文件是一种用于阐释电子控制单元(ECU)测量与校准数据的标准格式。该格式依据ASAP2(Automotive Standard Input Output Bus Protocol for Parameter Access)标准进行定义,并在电子控制单元的开发、测试及诊断环节中得到广泛运用。本指南将系统性地介绍A2L文件的编制流程及其遵循的规范,旨在为工程师群体提供具有实践价值的指导。 #### 二、A2L文件基础知识 1. **定义**:A2L文件是一种基于ASCII码的文本性载体,主要功能是存储电子控制单元内所有可测量及可校准对象的详细信息。 2. **作用**: - **参数管理**:系统性地记录电子控制单元中的参数配置详情。 - **诊断支持**:为故障诊断提供必要的数据支撑,包括故障代码的读取等操作。 - **软件开发**:在软件开发阶段,对参数配置进行辅助性管理。 3. **组成结构**: - **头部信息**:涵盖文件版本号、生成日期等基础性信息。 - **模块定义**:将每个电子控制单元设定为一个独立的模块进行详细描述。 - **测量点和校准通道**:明确电子控制单元内部测量点与校准通道的具体设置。 - **特征描述**:对电子控制单元的特定性能进行说明,例如温度传感器的性能曲线。 #### 三、A2L文件制作工具 - **ASAP2Editor**:由Vector Informatik GmbH开发的一款专业级工具,专门用于A2L...
内容概要:本文系统介绍了物理信息神经网络(PINNs)在求解布洛赫-托雷(Bloch-Torrey)方程中的具体应用,并提供了基于PyTorch框架的Python代码实现案例。研究通过将物理先验知识嵌入神经网络的损失函数中,结合深度学习方法高效求解复杂的偏微分方程,充分展现了PINNs在科学计算与工程仿真领域的优越性。文章详细阐述了模型架构设计、物理约束的数学表达、网络训练流程以及数值实验结果分析,突出了数据驱动方法与物理机理深度融合的研究范式,为相关领域的复杂系统建模提供了新的技术路径。; 适合人群:具备一定深度学习理论基础,熟练掌握PyTorch框架,从事科学计算、生物医学工程、数值模拟或物理建模等相关领域研究的研究生、科研人员及工程师。; 使用场景及目标:①深入理解物理信息神经网络(PINNs)的核心原理及其在偏微分方程求解中的具体实现方法;②掌握如何将物理定律(如扩散方程)转化为神经网络可优化的损失项;③复现并拓展该方法至扩散磁共振成像(dMRI)、材料科学等涉及布洛赫-托雷方程的实际物理系统仿真研究; 阅读建议:建议读者结合所提供的完整代码进行动手实践,重点关注损失函数的设计、初始/边界条件的施加方式以及超参数调优策略,并尝试将该框架迁移应用于其他类型的物理系统建模问题中,以深化对物理引导机器学习的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值