Ruby 中的闭包-代码块

看了一片文章https://ruby-china.org/topics/38385讲closure的。

写下一些感想:

闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的lexical作用域的外面执行。

当一个函数被写出来时,这个函数的closure就已经确定了。

javascript中有闭包的概念:https://www.cnblogs.com/chentianwei/p/9739714.html

Ruby中的关键字定义def是没有闭包的。它创建一个封闭的作用域。

但是Ruby有闭包的概念这就是--代码块。

a = 100

define_method :add_a do
  a = a + 1
end

puts add_a # => 101
puts add_a # => 102
puts add_a # => 103

这个例子使用了define_method方法搭配一个代码块来定义方法。我们就可以访问外部的作用域的局部变量a。

Ruby就是使用代码块来表示闭包的。

可以参考《Ruby元编程》相关章节的例子:

def my_method
  x = "GoodBye"
  puts yield("cruel")
end

x = "Hello"
my_method  do |y|
  "#{x}, #{y} world!"
end

代码块绑定了变量x。即外部作用域的变量跟着代码块一起走!

代码块的意义:

在Ruby的开源世界,代码块无处不在:

1.容错涉及:

Ruby承袭于Lisp,代码块的运行会自动返回最后一条语句或者表达式的值,于是有些库也考虑到了用代码块来进行容错处理。

例子:

> hash = {}
> value = hash.fetch(‘a‘) { ‘default value‘ }
 => "default value"

因为hash是空的,没有"a", 所以会返回代码块中的字符串,如果不提供代码块,就会报错?。

2. DSL

3. 蹩脚的函数

代码块可以看作是一个蹩脚的函数,虽然一般情况下可以作为某个方法的回调,但在Ruby中代码块需要依赖其他机制来存在,而不是JS中的函数那样独立存在。

当使用代码块来定义一个匿名函数时,需要搭配lambda关键字或Proc类来实现。

> c = lambda() {}
 => #<Proc:[email protected](irb):6 (lambda)>
> c.class
 => Proc

> (lambda() { ‘hello‘ }).call
 => "hello"
> (lambda() { ‘hello‘ })[]
 => "hello"
> (Proc.new { ‘hello‘ }).call
 => "hello"
> (Proc.new { ‘hello‘ })[]
 => "hello"

x = "tom"
(lambda() {"Hello,#{x}"}).call

以上都是常用的定义匿名函数的方式,本质上它们都是Proc类的实例,需要显式地利用Proc#call方法或者语法糖[]来调用它们。

总结:

这篇文章介绍了Ruby中的闭包概念, 它和封闭作用域的方法(使用def关键字定义的方法)有什么不同。

?? Ruby中定义了三个地方为封闭的作用领域(对应三个关键字):

  • 类定义 class
  • 模块定义 module
  • 方法def

区别于一般的方法,闭包在Ruby中以代码块的形式出现,它在Ruby世界中几乎无处不在,充当了一等公民。这种区分,不仅使我们的Ruby代码更加优雅,增添了可读性,还使得我们的编码过程更加简单。

原文地址:https://www.cnblogs.com/chentianwei/p/11438465.html

时间: 2024-10-13 12:17:04

Ruby 中的闭包-代码块的相关文章

ASP.NET 网页中的嵌入式代码块

将代码添加到 ASP.NET 网页中的默认模型要么创建一个代码隐藏类文件(代码隐藏页),要么将页的代码写到具有 runat="server" 特性的 script 块中(单文件页). 编写的代码通常会与页上的控件进行交互. 例如,通过从代码中设置控件的 Text(或其他)属性,可以在页上显示信息. 另一种可能是使用嵌入式代码块将代码直接嵌入到页中. 嵌入式代码块 嵌入式代码块是在呈现页面的过程中执行的服务器代码. 块中的代码可以执行编程语句,并调用当前页类中的函数. 下面的代码示例演示

关于Java中的静态代码块

一.静态代码块 ①特点:随着类的加载而执行,且只执行一次,不管创建了多少次对象实例,这个类中的静态代码块只会在第一次创建类实例或者直接使用类名调用静态方法时执行一次,且若第一次是使用类名调用静态方法,则会先执行静态代码块后才会执行相应方法.(这也说明创建类实例或者使用类名调用静态方法时,类都会被加载进内存).如果是StaticCode s=null;这样的声明语句,类是不会被加载入内存中的. ②功能:用于给类初始化(不是对象) 二.静态方法:①若只是创建含有静态方法的类的对象而没有调用静态方法,

java中的静态代码块、构造代码块、普通代码块和同步代码块总结

java中的4中代码块总结如下: * 加了static的是静态代码块,在类中写了一对{}是构造代码块,在方法中写了一对{}是普通代码块, * java中还有一种代码块是同步代码块,常用在多线程中, synchronized关键字, * 同步代码块格式是:synchronized(同步对象){} * 静态代码块 先于构造代码块 先于构造方法执行 * 静态代码块 先于普通代码块 先于构造方法执行 * 构造代码块和普通代码块按照程序逻辑顺序执行 package 面试题; class HelloA{ p

java中c#中statc 静态调用不同之处、c#的静态构造函数和java中的构造代码块、静态代码块

1.java和c#静态成员调用的不同之处 static 表示静态的,也就是共享资源,它是在类加载的时候就创建了 java中   可以通过实例来调用,也可以通过类名.成员名来调用,但是一般最好使用类名.成员这个方式,因为静态成员是属于类的,并不是属于具体的对象 c#中     只能通过类名.成员调用,并不能 用实例来进行调用 2.c#的静态构造函数和java中的构造代码块.静态代码块 c# 静态构造函数的特点:        1)静态构造函数不需要手动调用,系统自动调用        2)静态构造

java中的静态代码块,构造代码块,构造函数,普通代码块

java中的静态代码块,构造代码块,构造函数,普通代码块 静态代码块: 格式: public class Test1{ static{ System.out.println("这是一个静态代码块");  } } 说明: 1.静态代码块在类加载时也就是项目启动时运行并且只运行一次相当于main函数,有多个静态代码块从上往下依次执行,他是一种主动运行的机制. 2.静态代码块不能存在于任何方法中 构造代码块 格式: public class Test2{ { System.out.print

Java中的构造代码块

代码块 ----a静态代码块 ----b构造代码块 ----c普通代码块 执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. a.静态代码块: 静态代码块在加载该类的时候执行,且只执行一次! 1 class Test{ 2 public static void main(String args[]) 3 { 4 Demo d1=new Demo();Demo d2=new Demo(); 5 6 } 7 } 8 9 class Demo{ 10 static{

Gradle中的buildScript代码块

在编写Gradle脚本的时候,在build.gradle文件中经常看到这样的代码: build.gradle 1 2 3 4 5 6 7 8 9 buildScript { repositories { mavenCentral() } } repositories { mavenCentral() } 这样子很容易让人奇怪,为什么repositories要声明两次哪?buildscript代码块中的声明与下半部分声明有什么不同? 其实答案非常简单.buildscript中的声明是gradle脚

Java中的局部代码块、构造代码块、静态代码块

局部代码块: 作用:控制变量的生命周期: 在程序中,当我们已经使用完 x 后,并且在接下来的代码中,不会再用到x,那么就没必要让x 在内存中占用空间了,这用情况下,可以使用 局部代码块,将x及其所设计到的区域封装为局部代码块,他们在程序执行中顺序不变,只是在执行完成后消失. 表现形式,以代码体现如下: class TestDemo { public static void main(String[] args) { { int x = 9; System.out.println(x); } Sy

浅析Java中的构造代码块、静态代码块与构造方法

构造代码块.静态代码块与构造方法是三种不同的代码块,那么他们到底有什么区别呢? 一.简单认识一下构造代码块.静态代码块与构造方法 class A { //构造代码块 { System.out.println("构造代码块A"); } //静态代码块 static { System.out.println("静态代码块A"); } //构造方法 public A() { System.out.println("构造方法A"); } } 二.弄清三者