一元 & 运算符并在 Ruby 中将过程作为参数传递

2024-03-05

我无法理解下面的这段代码。

我了解一元与运算符并将过程作为参数传递给方法的想法。但我实在无法接受过去的事self to the language.call。我是这样理解的:我们正在过去self作为 proc/block 语言的参数。这对我来说没有任何意义。有人可以解释一下吗? :)

class Translator    
  def speak &language
    language.call(self)    
  end

  protected

  def french
    'bon jour'  
  end

  def spanish
    'hola'   
  end

  def turkey
    'gobble'   
  end

  def method_missing(*args)
    'awkward silence'
  end 
end

我们将它用于:

translator.speak(&:spanish)

这个示例将多个 Ruby 概念完美地结合在一起。因此,我将尝试解释所有这些内容。

  1. Blocks

Ruby 中的方法可以优雅地接受块(代码片段):

def run_code
  yield
end

run_code { puts 42 } # => prints 42
  1. 过程与块类似,但它们是实际的可寻址对象:
deep_thought = proc { puts 42 }
deep_thought.call # => prints 42
  1. 当调用方法时,您可以将过程转换为块&操作员:
def run_code
  yield
end

deep_thought = proc { puts 42 }
run_code(&deep_thought) # => prints 42
  1. 过程和块可以接受参数:
def reveal_answer
  yield 5_000
end

deep_thought = proc do |years_elapsed|
  years_elapsed >= 7_500_000 ? 42 : 'Still processing'
end

reveal_answer(&deep_thought) # => 'Still processing'
  1. 您可以使用以下命令将块转换为过程&在方法签名中:
def inspector(&block)
  puts block.is_a?(Proc)
  puts block.call
end

inspector { puts 42 } # => prints true and 42
inspector(&proc { puts 42 }) # => the same
  1. Symbol#to_proc创建一个过程,调用对象上同名的方法:
class Dummy
  def talk
    'wooooot'
  end
end

:talk.to_proc.call(Dummy.new) # => "wooooot"

换句话说,

:bar.to_proc.call(foo)

几乎相当于

foo.bar
  1. BasicObject#method_missing:

当您尝试调用对象的方法时,Ruby 会遍历它的祖先链,搜索具有该名称的方法。链是如何构建的是一个不同的话题,足够长到改天,重要的是如果直到最底层都没有找到方法(BasicObject),在同一条链上执行第二次搜索 - 这次是针对名为method_missing。它作为参数传递原始方法的名称加上它收到的任何参数:

class MindlessParrot
  def method_missing(method_name, *args)
    "You caldt #{method_name} with #{args} on me, argh!"
  end
end

MindlessParrot.new.foo          # => "You caldt foo with [] on me, argh!"
MindlessParrot.new.bar :baz, 42 # => "You caldt bar with [:baz, 42] on me, argh!"

那么这一切在我们的具体案例中意味着什么呢?让我们假设没有protected.


translator.speak(&:spanish)

调用方法Translator#speak with :spanish转换为块。


Translator#speak获取该块并将其转换为一个过程,名为language,并调用它,传递self作为论证。


self是一个实例Translator,因此,它有方法speak, french, spanish, turkey and method_missing.


And so:

Translator.new.speak(&:spanish)

相当于:

:spanish.to_proc.call(Translator.new)

这相当于:

Translator.new.spanish

给我们"hola".


现在,采取protected回来,我们所有的语言方法translator对象仍然存在,但外人无法直接访问它们。


就像你不能打电话一样

Translator.new.spanish

并期望"hola"回来,你不能打电话

Translator.new.speak(&:spanish)




并且由于该方法不可直接访问,因此被认为未找到并且method_missing被称为,从而给我们"awkward silence".

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一元 & 运算符并在 Ruby 中将过程作为参数传递 的相关文章

随机推荐

  • 如何设置Xcode“调试/发布目标设置”?

    我在这里找到了一组很棒的宏Objective C 宏 http blog coriolis ch 2009 01 05 macros for xcode 我把 if DEBUG 1 define macros 在我的头文件中 现在我根本不知
  • 如何在 Swift 2.0 中保持标题单元格与表格视图单元格一起移动

    我正在尝试创建一个表格视图 该表格视图在表格视图中间启动标题 然后可以将添加的表格视图单元格向上滚动到顶部 然后停止 然后表格视图单元格可以在其 下方 滚动 我让标题位于 tableview 的中间 但 tableView Cells 只是
  • 启用自定义键盘 iOS8 的应用内购买

    我正在为 iOS 构建自定义键盘 我想知道如何启用应用内购买 该文档指出我可以通过包含的应用程序启用应用程序内购买 但我不确定这意味着什么 技术上 有没有人通过应用内购买构建了 iPhone 扩展 可以给我一些指导 扩展程序与应用程序捆绑在
  • 您认识 16 位时间戳吗?

    我正在使用 Google 书签 它返回 16 位时间戳 我似乎无法在 C 中识别该时间戳以将其转换为真实日期 有什么想法吗 如何转动这个时间戳 1278276905502403在 C 中有意义的东西 这看起来就像以微秒为单位的 UNIX 时
  • 为什么 getQueryString() 在带有 h:commandButton 的 jsf 支持 bean 中不起作用

    我已经在菜单栏顶部构建了一个登录代码片段 如果用户通过导航进入任何页面并突然按下登录按钮 我希望看到该人经过身份验证 同时停留在他最初来自的页面上 所以我在支持 bean 上使用了这个 HttpServletRequest request
  • 等待 Kubernetes 或 Google Container Engine 中的作业/Pod 完成

    在 Kubernetes 或 Google Container Engine 中 脚本中等待作业或 Pod 完成的最佳方式是什么 特别是 最好得到通知而不是轮询状态kubectl 但我会很高兴有一个相当有效的循环 并且裂缝之间没有任何滑动
  • 了解 matplotlib 事件处理:什么是 event 和 mpl_connect?

    我希望能够在按下散点图中的点时显示值 解决方案在这里找到 当鼠标悬停在 matplotlib 中的某个点上时可以显示标签吗 https stackoverflow com questions 7908636 possible to make
  • .NET Core 2.2 迁移生成器无法删除索引

    我正在尝试从 IdentityUserRole 表中名为 UserRole 的列中删除索引 外键 UserRole 有 2 列 用户 ID 和角色 ID 两者都是主键 protected override void OnModelCreat
  • 在*某些* WebAPI 控制器上禁用 SSL 客户端证书?

    为未来的读者编辑 不幸的是 赏金奖励答案 不起作用 我现在对此无能为力 但请阅读我自己的答案 下面 通过测试 确认可以使用最少的代码更改 我们有一个完全采用 ASP NET WebAPI 2 2 的 Azure 云服务 WebRole 无
  • Maven Jetty 插件中的 Jetty JNDI 错误

    我正在尝试配置一个可通过调用 Maven Jetty 插件使用的 JNDI 数据源 我试图在 WAR 文件外部执行此操作 以便以后使用 Jetty 部署我们的 web 应用程序的任何人都不必编辑 WAR 的 WEB INF 目录内的配置文件
  • Android:ViewPager - PagerSlidingTabStrip,state_selected 上的自定义选项卡背景

    当每个选项卡都在时 我需要为每个选项卡使用自定义背景状态选择模式 但当我选择一个选项卡时仍然没有任何反应 我使用这样的选择器 tab selector xml
  • PHP 中的超链接自动生成图像

    我正在为我的第一个客户建立一个网站 使用WordPress 的 Simplicity Lite 主题 http wordpress org themes simplicity lite 我想以某种方式改变主题 以便在特色框位置 幻灯片放映的
  • 在 CSS Bootstrap jquery modal 中将元素暴露在 modal-backdrop 之外

    我正在使用 CSS Bootstrap 的 Modal 功能 它运行得很好 但是 我想添加一项功能 当模式对话框打开并且网页的其余部分被 modal backdrop 覆盖时 来自页面结构范围内不同位置的外部元素之一可以是暴露在背景之上 d
  • 使用中继现代 graphql 添加突变

    我正在尝试使用中继添加用户 下面是我的架构文件 schema graphql createUser input CreateUserInput UserPayload input CreateUserInput clientMutation
  • 如何判断点击了表格中的哪一行号?

    我有一个如下表 table tr td 1 td td 1 td td 1 td tr tr td 2 td td 2 td td 2 td tr tr td 3 td td 3 td td 3 td tr table 当用户单击表时 如何
  • 核心数据问题 - 选择分组依据/具有最大值

    假设我有两个实体 每个消息都属于一个消息线程 如何获取所有消息线程以及该线程上相应的最后一条消息 通常 在 SQL 中 我会这样做 按时间戳 max timeStamp 的线程从消息组中选择 其一 我认为 Core Data 不允许在其谓词
  • C++ Builder vs Delphi vs MFC

    我正在学习MFC 发现它不太好用 我听说过很多关于 Delphi 的事 对 Delphi 的研究让我接触到了 C Builder C Builder 是否提供了 C MFC 的严肃且良好的替代方案 C Builder 比 MFC 更好吗 C
  • Chrome扩展:从popup.js访问background.js的变量

    如果我正在使用chrome extension getBackgroundPage https developer chrome com extensions extension html method getBackgroundPage
  • 如何关闭窗口.打开

    我知道你可以用 window close 关闭 window open 但还有其他方法吗 我有一个打开 facebook 连接的弹出窗口 我想在用户连接到 facebook 时关闭弹出窗口 然后刷新父窗口 我认为过去我使用过 TARGET
  • 一元 & 运算符并在 Ruby 中将过程作为参数传递

    我无法理解下面的这段代码 我了解一元与运算符并将过程作为参数传递给方法的想法 但我实在无法接受过去的事self to the language call 我是这样理解的 我们正在过去self作为 proc block 语言的参数 这对我来说