The most interesting addition to Ruby 2.3.0 is the Safe Navigation Operator(&.). A similar operator has been present in C# and Groovy for a long time with a slightly different syntax - ?.. So what does it do?

Scenario

Imagine you have an account that has an owner and you want to get theowner’s address. If you want to be safe and not risk a Nil error you would write something like the following:

if account && account.owner && account.owner.address
...
end

This is really verbose and annoying to type. ActiveSupport includes the trymethod which has a similar behaviour (but with few key differences that will be discussed later):

if account.try(:owner).try(:address)
...
end

It accomplishes the same thing - it either returns the address or nil if some value along the chain is nil. The first example may also return false if for example the owner is set to false.

Using &.

We can rewrite the previous example using the safe navigation operator:

account&.owner&.address

The syntax is a bit awkward but I guess we will have to deal with it because it does make the code more compact.

More examples

Let’s compare all three approaches in more detail.

account = Account.new(owner: nil) # account without an owner

account.owner.address
# => NoMethodError: undefined method `address' for nil:NilClass account && account.owner && account.owner.address
# => nil account.try(:owner).try(:address)
# => nil account&.owner&.address
# => nil

No surprises so far. What if owner is false (unlikely but not impossible in the exciting world of shitty code)?

account = Account.new(owner: false)

account.owner.address
# => NoMethodError: undefined method `address' for false:FalseClass ` account && account.owner && account.owner.address
# => false account.try(:owner).try(:address)
# => nil account&.owner&.address
# => undefined method `address' for false:FalseClass`

Here comes the first surprise - the &. syntax only skips nil but recognizesfalse! It is not exactly equivalent to the s1 && s1.s2 && s1.s2.s3 syntax.

What if the owner is present but doesn’t respond to address?

account = Account.new(owner: Object.new)

account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8> account && account.owner && account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>` account.try(:owner).try(:address)
# => nil account&.owner&.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

Oops, the try method doesn’t check if the receiver responds to the given symbol. This is why it’s always better to use the stricter version of try -try!:

account.try!(:owner).try!(:address)
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

Pitfalls

As Joeri Samson pointed out in the comments, this section is actually wrong - I mistakenly used ?. instead of &.. But I still think that the last example is confusing and nil&.nil? should return true.

Be careful when using the &. operator and checking for nil values. Consider the following example:

nil.nil?
# => true nil?.nil?
# => false nil&.nil?
# => nil

Array#dig and Hash#dig

The #dig method is, in my opinion, the most useful feature in this version. No longer do we have to write abominations like the following:

address = params[:account].try(:[], :owner).try(:[], :address)

# or

address = params[:account].fetch(:owner) .fetch(:address)

You can now simply use Hash#dig and accomplish the same thing:

address = params.dig(:account, :owner, :address)

Final words

I really dislike dealing with nil values in dynamic languages  and think the addition of the safe operator and the digmethods is really neat. Note that Ruby 2.3.0 is still not released and some things might change in the final version.

The Safe Navigation Operator (&.) in Ruby的更多相关文章

  1. C# 6.0 (C# vNext) 新功能之:Null-Conditional Operator(转)

    Null-Conditional Operator 也叫 Null propagating operator 也叫 Safe Navigation Operator 看名字,应该就有点概念了.如果还不 ...

  2. coffeescript 1.8.0 documents

    CoffeeScript is a little language that compiles into JavaScript. Underneath that awkward Java-esque ...

  3. how to use coffee script

    TABLE OF CONTENTS TRY COFFEESCRIPT ANNOTATED SOURCE CoffeeScript is a little language that compiles ...

  4. coffeescript 1.6.3使用帮助

    CoffeeScript is a little language that compiles into JavaScript. Underneath that awkward Java-esque ...

  5. CoffeeScript 更优美的Javascript

    CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的心脏. CoffeeScript 尝试用简洁的方式展 ...

  6. groovy-运算符

    算术和条件运算符 Groovy支”!”操作符,例如: 1 def expression = false 2 assert !expression 基于集合的运算符: Spread Operator ( ...

  7. Scala Option类型

    转载自: Scala 初学者指南, 这里有一系列很棒的文章 类型 Option 可能你已经见过它在 Map API 中的使用:在实现自己的提取器时,我们也用过它, 然而,它还需要更多的解释. 你可能会 ...

  8. Spring生态研习【二】:SpEL(Spring Expression Language)

    1. SpEL功能简介 它是spring生态里面的一个功能强大的描述语言,支在在运行期间对象图里面的数据查询和数据操作.语法和标准的EL一样,但是支持一些额外的功能特性,最显著的就是方法调用以及基本字 ...

  9. Spring框架文档与API(4.3.6版本)

    http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ Table of Contents I ...

随机推荐

  1. React反模式 —— 如何不使用JSX地动态显示组件

    欢迎指导与讨论 : ) 前言 文章的最后能写出以 Modal.open( ) 这种调用形式,动态显示React对话框组件的写法(类似于ant design),同时涉及数据交互(数据能异步地返回给调用者 ...

  2. libsvm的数据格式及制作

    1.libsvm数据格式 libsvm使用的训练数据和检验数据文件格式如下: [label] [index1]:[value1] [index2]:[value2] … [label] [index1 ...

  3. [LeetCode] Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...

  4. C#文件目录操作完全手册

    需要 using System.IO; 1) 相对路径转绝对路径string fullfolder = HttpContext.Current.Server.MapPath(folder); 2) 文 ...

  5. .Net mvc 根据前台参数动态绑定对象

    业务需求:根据前台界面的参数,动态绑定对象 <param name="colNames">属性名拼接字符串</param><param name=&q ...

  6. jquery.on()超级方法

    $.on()方法是jquery1.7之后的一个超级方法,将事件绑定和事件委托整合到一个函数中去,支持绑定多个事件,并且可以绑定自定义事件.使用起来很方便. demo传送门 事件委托 首先说一下事件委托 ...

  7. Android基础总结(九)

    多媒体概念(了解) 文字.图片.音频.视频 计算机图片大小的计算(掌握) 图片大小 = 图片的总像素 * 每个像素占用的大小 单色图:每个像素占用1/8个字节 16色图:每个像素占用1/2个字节 25 ...

  8. svn服务器地址变换以后,mac下的处理方法

    svn服务器地址变换之后,mac下的处理方法 svn服务器地址变换之后,mac下的处理方法 1.进入终端,进入项目所在的文件夹下: cd 项目位置/ 2.查看svn信息 svn info 3.输出结果 ...

  9. 实例解析防抖动(Debouncing)和节流阀(Throttling)

    http://outofmemory.cn/javascript/js-Debounce-throttle

  10. Windows常用快捷方式

    总结了其他常用的快捷方式: Ctrl+C 复制 . Ctrl+V粘贴. Ctrl+X剪切. Delete删除. Alt+Tab 应用程序切换 Ctrl+Alt+Delete  Ctrl+shift+E ...