From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: poffice@blade.nagaokaut.ac.jp Delivered-To: poffice@blade.nagaokaut.ac.jp Received: from kankan.nagaokaut.ac.jp (kankan.nagaokaut.ac.jp [133.44.2.24]) by blade.nagaokaut.ac.jp (Postfix) with ESMTP id 9ABCC19C0022 for ; Fri, 30 Oct 2015 04:05:05 +0900 (JST) Received: from voscc.nagaokaut.ac.jp (voscc.nagaokaut.ac.jp [133.44.1.100]) by kankan.nagaokaut.ac.jp (Postfix) with ESMTP id 2AC22B5D8A0 for ; Fri, 30 Oct 2015 04:33:12 +0900 (JST) Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by voscc.nagaokaut.ac.jp (Postfix) with ESMTP id 2658D952439 for ; Fri, 30 Oct 2015 04:33:11 +0900 (JST) Received: from [221.186.184.76] (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id BC6D01204DE; Fri, 30 Oct 2015 04:33:06 +0900 (JST) X-Original-To: ruby-core@ruby-lang.org Delivered-To: ruby-core@ruby-lang.org Received: from o2.heroku.sendgrid.net (o2.heroku.sendgrid.net [67.228.50.55]) by neon.ruby-lang.org (Postfix) with ESMTPS id A067C12047A for ; Fri, 30 Oct 2015 04:33:03 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sendgrid.me; h=from:to:references:subject:mime-version:content-type:content-transfer-encoding:list-id; s=smtpapi; bh=FypdK2O1k+RFrXlg5RKXbHRdNWs=; b=M48kkjaCpvY8Uda4cE sCGvMgUI+BSvgYF3vE6EQ02ZR0OcihRIH747ucTh2Bs1DEvkWTbDgYhsINo4XmWz EuersdsoMDmctM0MpA1LVcAN9gcnqFWssckeX91+STh0Kg1+yvu+a5YyyPcEtxVf yQGBctR0wId0K2wOYDdkrkIFk= Received: by filter0846p1mdw1.sendgrid.net with SMTP id filter0846p1mdw1.26076.5632746940 2015-10-29 19:32:57.666304565 +0000 UTC Received: from herokuapp.com (ec2-54-82-2-136.compute-1.amazonaws.com [54.82.2.136]) by ismtpd0003p1iad1.sendgrid.net (SG) with ESMTP id L9nOFStXQbCGYOeXZS6AHg for ; Thu, 29 Oct 2015 19:32:57.596 +0000 (UTC) Date: Thu, 29 Oct 2015 19:32:57 +0000 From: alonecomp@gmail.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Redmine-MailingListIntegration-Message-Ids: 45900 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 11537 X-Redmine-Issue-Author: hsbt X-Redmine-Issue-Assignee: matz X-Redmine-Sender: dotnetwise X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS7U2VvvYGNzi5rwDMMBsouiYugiD51ZwIv2CZ YfXkXM197OBAXA/v+6GyuV7A2JVTNWTka41cB1p2yUt71wBZf7yRuuuy0yT6NU64UbnoKVg150LCl3 gJMqKMIhjVqbV3SdU1XfFcHlR3vInLY1do+4 X-ML-Name: ruby-core X-Mail-Count: 71271 Subject: [ruby-core:71271] [Ruby trunk - Feature #11537] Introduce "Safe navigation operator" X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #11537 has been updated by Laurentiu Macovei. The same discussion happens to be on TypeScript and ES6 worlds. Using .. instead of ?. or .? because it's way more clear when you are using the ternary ? : operator on the same line. If it's not a conflict in Ruby syntax perhaps worths looking at https://esdiscuss.org/topic/existential-operator-null-propagation-operator#content-65 https://github.com/Microsoft/TypeScript/issues/16#issuecomment-152275052 Posting the markdown info from there: This would be amazing operator!! Especially for `ES6`/`ES7`/`TypeScript` - and why not `Ruby` ? ```js var error = a.b.c.d; //this would fail with error if a, b or c are null or undefined. var current = a && a.b && a.b.c && a.b.c.d; // the current messy way to handle this var currentBrackets = a && a['b'] && a['b']['c'] && a['b']['c']['d']; //the current messy way to handle this var typeScript = a?.b?.c?.d; // The typescript way of handling the above mess with no errors var typeScriptBrackets = a?['b']?['c']?['d']; //The typescript of handling the above mess with no errors ``` However I propose a more clear one - as not to confuse ? from the a ? b : c statements with a?.b statements: ```js var doubleDots = a..b..c..d; //this would be ideal to understand that you assume that if any of a, b, c is null or undefined the result will be null or undefined. var doubleDotsWithBrackets = a..['b']..['c']..['d']; ``` For the bracket notation, I recommend two dots instead of a single one as it's consistent with the others when non brackets are used. Hence only the property name is static or dynamic via brackets. Two dots, means if its null or undefined stop processing further and assume the result of expression is null or undefined. (as d would be null or undefined). Two dots make it more clear, more visible and more space-wise so you understand what's going on. This is not messing with numbers too - as is not the same case e.g. ```js 1..toString(); // works returning '1' var x = {}; x.1 = {y: 'test' }; //fails currently x[1] = {y: 'test' }; //works currently var current = x[1].y; //works var missing= x[2].y; //throws exception var assume= x && x[2] && x[2].y; // works but very messy ``` About numbers two options: Your call which one can be adopted, but I recommend first one for compatibility with existing rules! 1. Should fail as it does now (`x.1.y` == `runtime error`) ```js var err = x..1..y; // should fail as well, since 1 is not a good property name, nor a number to call a method, since it's after x object. ``` 2. Should work since it understands that is not a number calling a property from `Number.prototype` ```js var err = x..1..y; // should work as well, resulting 'test' in this case var err = x..2..y; // should work as well, resulting undefined in this case ``` With dynamic names: ```js var correct1 = x..[1]..y; //would work returning 'test' var correct2 = x..[2]..y; //would work returning undefined; ``` What do you think folks? P.S. `foo?.bar` and `foo?['bar']` syntax would work too. However the using both current `?` `:` operator and `?.` might be very confusing on the same line. e.g. using `?.` and `?['prop']` ```js var a = { x: { y: 1 } }; var b = condition ? a?.x.?y : a?.y?.z; var c = condition ? a?['x']?['y'] : a?['y']?['z']; ``` as opposed to double dots `..` and `..['prop']` ```js var a = { x: { y: 1 } }; var b = condition ? a..x..y : a..y..z; var c = condition ? a..['x']..['y'] : a..['y']..['z']; ``` ##### Which one does look more clear to you? ---------------------------------------- Feature #11537: Introduce "Safe navigation operator" https://bugs.ruby-lang.org/issues/11537#change-54644 * Author: Hiroshi SHIBATA * Status: Closed * Priority: Normal * Assignee: Yukihiro Matsumoto ---------------------------------------- I sometimes write following code with rails application: ```ruby u = User.find(id) if u && u.profile && u.profile.thumbnails && u.profiles.thumbnails.large ... ``` or ```ruby # Use ActiveSupport if u.try!(:profile).try!(:thumbnails).try!(:large) ... ``` I hope to write shortly above code. Groovy has above operator named "Safe navigation operator" with "`?.`" syntax. Ruby can't use "`?.`" operator. Can we use "`.?`" syntax. like this: ```ruby u = User.find(id) u.?profile.?thumbnails.?large ``` Matz. How do you think about this? -- https://bugs.ruby-lang.org/