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 6D41E1AE022E for ; Wed, 7 Sep 2016 21:11:38 +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 7FE96B5D9BB for ; Wed, 7 Sep 2016 21:44:11 +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 4CE5E18CC821 for ; Wed, 7 Sep 2016 21:44:12 +0900 (JST) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id B5D941204AC; Wed, 7 Sep 2016 21:44:10 +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 1B389120495 for ; Wed, 7 Sep 2016 21:44:07 +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=0BWtg3877MXqKP0rXCUY3jjKTLQ=; b=D1/6ETgH7XtwX4r8cC qIqxkvcN/DICYwWwnH5C315MYFMQpoWCk8xHcnvvHiKKkm8nxTbIN63i3GVEogQn 4+mQCbwsALKgb9CVmne4qjkbtW3PvFA/OQXCSgYfdpUu0JKIxd9LPi9YHNOZR8gD mfeHJpcofoqY9i9yN8u7blC0o= Received: by filter0406p1mdw1.sendgrid.net with SMTP id filter0406p1mdw1.18852.57D00B7717 2016-09-07 12:43:35.697681728 +0000 UTC Received: from herokuapp.com (ec2-54-221-182-62.compute-1.amazonaws.com [54.221.182.62]) by ismtpd0004p1iad1.sendgrid.net (SG) with ESMTP id TAHx0HrAQ56xhQWbSFHyEw Wed, 07 Sep 2016 12:43:35.726 +0000 (UTC) Date: Wed, 07 Sep 2016 12:43:35 +0000 From: headius@headius.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 52003 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 12086 X-Redmine-Issue-Author: shugo X-Redmine-Sender: headius 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/Ymy4QrNMhiuLXJG8OTL2vJD1yS7P7IOqKq1779SZoNun9i7A510hviP4OOnR68 UJIDJCApYeWXpLtx+izI8ykK7pvkil2eBd2FUSk5XSJq3mK0IFpOlSVRrMKLci5Ndq62raGBQYgMzs f4U7aKDZYXjBLWBzDcbR29hdELG9lxVomMBQn/CXJdb32jcd53rchgevng== X-ML-Name: ruby-core X-Mail-Count: 77208 Subject: [ruby-core:77208] [Ruby trunk Feature#12086] using: option for instance_eval etc. 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: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #12086 has been updated by Charles Nutter. I'll echo Tom's comments...this is dynamically-scoped refinements all over again, which we discussed heavily. There's two big reasons why this is a risk: * Performance. We decided that refinements would be lexical *only* in order to limit the impact of refinements on non-refined code. There's no way to treat a block as non-refined code since it might be refined at any time. I am interested to see how MRI can refine any block anywhere without impacting non-refined performance. * Readability. Now EVERY block in the system could potentially get refined. You will NEVER again be able to look at a piece of code in a block and know it's calling the methods you want it to call. Back when we were first putting refinements together, we all agreed to keep them lexical. This is not lexical anymore. I guess I'm very confused why this feature is needed for the DSL example. rspec implements a very similar DSL and does not use refinements today. We could make this work and still keep refinements lexically scoped if we allowed using to happen within a block: ```ruby require "radd_djur" calc = RaddDjur::Grammar.new(:expr) { using RaddDjur::DSL define :expr do # refined call to "define" [:int, "+", :int].bind { |x, *, y| # refined "bind" ret x + y # refined "ret" and "+" } / # refined "/" [:int, "-", :int].bind { |x, *, y| # etc ret x - y } ... ``` I can't recall why we wanted to avoid "using" within a block or method body. I still believe this should be a lower-level language feature, as a keyword or similar. The more dynamic you make it, the more unpredictable and unreliable code is going to become. I'll have a look at the proposed implementation. ---------------------------------------- Feature #12086: using: option for instance_eval etc. https://bugs.ruby-lang.org/issues/12086#change-60423 * Author: Shugo Maeda * Status: Open * Priority: Normal * Assignee: ---------------------------------------- Currently refinements can be activated only in toplevel or class/module definitions. If they can be activated in block-level, it's useful to implement internal DSLs. How about to add a new option using: for Kernel#instance_eval and Moule#{class,module}_eval? ```ruby module FixnumDivExt refine Fixnum do def /(other) quo(other) end end end p 1 / 2 #=> 0 instance_eval(using: FixnumDivExt) do p 1 / 2 #=> (1/2) end p 1 / 2 #=> 0 ``` Proof-of-concept implementation is available at . In my previous proposal before Ruby 2.0, refinements used in a class or module are implicitly activated by instance_eval and class_eval, but now I think it's better to explicitly specify refinements to be activated. Considerations: * In the PoC implementation, refined methods are not cached inline, and thus it decreases the performance of refined method call. If there is a way to guarantee that blocks never be evaluated in different environments, refined methods can be cached inline. * {instance,class,module}_exec cannot be extended in the same way, because they take arbitrary arguments and there's no way to distinguish an option hash from the last argument hash. -- https://bugs.ruby-lang.org/