Forum: Ruby Syntactic sugar idea

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
E0526a6bf302e77598ef142d91bdd31c?d=identicon&s=25 Daniel DeLorme (Guest)
on 2009-05-14 04:44
(Received via mailing list)
It seems that often an object will be passed into a block only to invoke
a method of that object:
   arr.map{ |obj| obj.some_method }

So I had the (weird? stupid?) thought that it would be nice to have some
syntactic sugar like this:
   arr.map{ .some_method }

Does that make any sense?
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-05-14 04:53
(Received via mailing list)
On Wed, May 13, 2009 at 10:42 PM, Daniel DeLorme <dan-ml@dan42.com>
wrote:
> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>  arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>  arr.map{ .some_method }
>
> Does that make any sense?

>> RUBY_VERSION
=> "1.9.1"
>> %w[foo bar baz].map(&:upcase)
=> ["FOO", "BAR", "BAZ"]

On Ruby 1.8.6, you can implement this easily as:

class Symbol
  def to_proc
    lambda { |x| x.send(self)
  end
end

-greg
8853f712852b03ba6646b59b1723f44d?d=identicon&s=25 Flower Born (flowerborn)
on 2009-05-14 04:55
(Received via mailing list)
* Daniel DeLorme <dan-ml@dan42.com> [2009-05-14 11:42:31 +0900]:

> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>   arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>   arr.map{ .some_method }

You can do arr.map(&:some_method) in ruby 1.9

-J
E0526a6bf302e77598ef142d91bdd31c?d=identicon&s=25 Daniel DeLorme (Guest)
on 2009-05-14 05:04
(Received via mailing list)
Jan wrote:
> You can do arr.map(&:some_method) in ruby 1.9
Yes, I know, and that was kind of my point. The to_proc conversion
became popular because people want a shortcut notation for this common
case, but IMHO map(&:foo) is way uglier than map{.foo}, and as a bonus
you could even do map{.foo.bar}  :-)

-Daniel
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-05-14 05:07
(Received via mailing list)
On Wed, May 13, 2009 at 11:03 PM, Daniel DeLorme <dan-ml@dan42.com>
wrote:

> Yes, I know, and that was kind of my point. The to_proc conversion
> became popular because people want a shortcut notation for this common
> case, but IMHO map(&:foo) is way uglier than map{.foo}, and as a bonus you
> could even do map{.foo.bar}  :-)

I don't know.   I think they're about the same in terms of looks, and
the former doesn't require changes to the parser.

-greg
Ef3aa7f7e577ea8cd620462724ddf73b?d=identicon&s=25 Rob Biedenharn (Guest)
on 2009-05-14 05:34
(Received via mailing list)
On May 13, 2009, at 11:07 PM, Gregory Brown wrote:
> the former doesn't require changes to the parser.
>
> -greg


plus, doing your .foo.bar has to contend with .foo being nil (or
otherwise having a NoMethodError for :bar)

some_collection.map{|e|e.foo.bar}

really isn't too bad anyway and if you want to handle the possible
exception:

some_collection.map{|e|e.foo.bar rescue nil}

possibly with a .compact thrown on the end.

The parser already refused to treat .5 as a Float literal insisting
that it be 0.5 so I doubt that .foo would get any more favorable
treatment as a special case (since .5 isn't really all that special).

-Rob

Rob Biedenharn    http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
E0526a6bf302e77598ef142d91bdd31c?d=identicon&s=25 Daniel DeLorme (Guest)
on 2009-05-14 06:16
(Received via mailing list)
Rob Biedenharn wrote:
> The parser already refused to treat .5 as a Float literal insisting that
> it be 0.5 so I doubt that .foo would get any more favorable treatment as
> a special case (since .5 isn't really all that special).

Well, you never know... Matz *did* add the Symbol#to_proc conversion in
1.9 and also the foo\n.bar "fluent interface" syntax. So apparently
trivial changes *do* make their way into core... sometimes.

-Daniel
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-05-14 06:28
(Received via mailing list)
Daniel DeLorme wrote:
> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>   arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>   arr.map{ .some_method }
>
> Does that make any sense?

It would be nice for avoiding instance_eval in DSLs:

@x = 400
@y = 300

config "my window" do
   .width @x
   .height @y
end

but I just don't see how to fit it into ruby...
31e038e4e9330f6c75ccfd1fca8010ee?d=identicon&s=25 Gregory Brown (Guest)
on 2009-05-14 07:14
(Received via mailing list)
On Thu, May 14, 2009 at 12:16 AM, Daniel DeLorme <dan-ml@dan42.com>
wrote:
> Rob Biedenharn wrote:
>>
>> The parser already refused to treat .5 as a Float literal insisting that
>> it be 0.5 so I doubt that .foo would get any more favorable treatment as a
>> special case (since .5 isn't really all that special).
>
> Well, you never know... Matz *did* add the Symbol#to_proc conversion in
> 1.9 and also the foo\n.bar "fluent interface" syntax. So apparently
> trivial changes *do* make their way into core... sometimes.

But Symbol#to_proc is not a parser change. It's just using an existing
hook that has been around in Ruby 1.8

-greg
E8a419959139f3f505b49bb95f7e7afe?d=identicon&s=25 Joshua Ballanco (jballanc)
on 2009-05-14 07:20
(Received via mailing list)
On May 14, 2009, at 12:27 AM, Joel VanderWerf wrote:

>
> but I just don't see how to fit it into ruby...
Isn't this essentially the "with" syntax from Javascript? I think that
could fit into a future version of Ruby...


- Josh
E0526a6bf302e77598ef142d91bdd31c?d=identicon&s=25 Daniel DeLorme (Guest)
on 2009-05-14 08:09
(Received via mailing list)
Gregory Brown wrote:
> On Thu, May 14, 2009 at 12:16 AM, Daniel DeLorme <dan-ml@dan42.com> wrote:
>> Well, you never know... Matz *did* add the Symbol#to_proc conversion in
>> 1.9 and also the foo\n.bar "fluent interface" syntax. So apparently
>> trivial changes *do* make their way into core... sometimes.
>
> But Symbol#to_proc is not a parser change. It's just using an existing
> hook that has been around in Ruby 1.8

But the fluent interface change *is* a parser change. My point was just
that seemingly trivial requests *can* make it into the core, whether
they're a syntax change or not.

-Daniel
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-05-14 09:16
(Received via mailing list)
2009/5/14 Daniel DeLorme <dan-ml@dan42.com>:
>
> But the fluent interface change *is* a parser change. My point was just that
> seemingly trivial requests *can* make it into the core, whether they're a
> syntax change or not.

We always need to balance cost and benefit.  In this case to me the
benefit seems to be outweighed by costs whereas the other change can
have an impact on readability.  YMMV though.

Cheers

robert
163755a5d3a5c57bd79c4f41bdda7a22?d=identicon&s=25 Clifford Heath (Guest)
on 2009-05-14 10:16
(Received via mailing list)
Robert Klemme wrote:
> We always need to balance cost and benefit.  In this case to me the
> benefit seems to be outweighed by costs

Right, what folk might not realise is that the 1.8 version constructed
an object on each usage which had to be GC'd later, whereas in the 1.9
version it can be free. So there was good reason to support it directly.

Clifford Heath.
Ca515d239bf09ffe970af1da4174eb03?d=identicon&s=25 Lars Christensen (Guest)
on 2009-05-14 11:33
(Received via mailing list)
On Thu, May 14, 2009 at 4:42 AM, Daniel DeLorme <dan-ml@dan42.com>
wrote:
> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>  arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>  arr.map{ .some_method }

I sometimes miss Perl's $_. Without a parser change, it could be used
as the default name for block parameters:

   arr.sort_by { $_.size }
   File.open("logfile", "a") { $_.puts logtext }
   arr.map { foo2bar($_) }

Then I remember how people abuse it and avoid using appropriately
named variables, and I am again happy about the little extra code I
have to write.
4feed660d3728526797edeb4f0467384?d=identicon&s=25 Bill Kelly (Guest)
on 2009-05-14 12:29
(Received via mailing list)
From: "Lars Christensen" <larschbelunktumdk@gmail.com>
>
> I sometimes miss Perl's $_.

Not that I'm advocating its use, but... Ruby does support $_
for perl-like command line scripting:

$ ruby -ne 'puts "dollar_underscore is: #$_"' /usr/share/dict/words |
head
dollar_underscore is:
dollar_underscore is: A
dollar_underscore is: A's
dollar_underscore is: AOL
dollar_underscore is: AOL's
dollar_underscore is: Aachen
dollar_underscore is: Aachen's
dollar_underscore is: Aaliyah
dollar_underscore is: Aaliyah's
dollar_underscore is: Aaron


Regards,

Bill
134ea397777886d6f0aa992672a50eaa?d=identicon&s=25 Mark Thomas (Guest)
on 2009-05-14 14:05
(Received via mailing list)
This is a neat idea, but wouldn't it conflict with the "fluent
interface" construct? Using Joel's DSL example:

config "my window" do
   .width @x
   .height @y
end

if we changed it to

config "my window" do
   .width calculate_width
   .height @y
end

Now how does the parser know what .height refers to: calculate_width,
or the implicit block variable?
Ede2aa10c6462f1d825143879be59e38?d=identicon&s=25 Charles Oliver Nutter (Guest)
on 2009-05-14 15:36
(Received via mailing list)
Daniel DeLorme wrote:
> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>   arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>   arr.map{ .some_method }
>
> Does that make any sense?

Groovy has this in the form of the "it" magic variable:

[1,2,3].each {puts it}

While I absolutely hate the moniker "it" the idea itself has grown on
me. Perhaps something more scala-like:

[1,2,3].each {puts _}

Or a pseudo-global:

[1,2,3].each {puts $it}

I hacked "it" to work in JRuby once recently, and it's not difficult.

- Charlie
Ede2aa10c6462f1d825143879be59e38?d=identicon&s=25 Charles Oliver Nutter (Guest)
on 2009-05-14 15:38
(Received via mailing list)
Robert Klemme wrote:
> We always need to balance cost and benefit.  In this case to me the
> benefit seems to be outweighed by costs whereas the other change can
> have an impact on readability.  YMMV though.

The cost isn't high. 15 minutes of work in JRuby, probably more in CRuby
but not by a lot.

- Charlie
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2009-05-14 15:45
(Received via mailing list)
2009/5/14 Charles Oliver Nutter <charles.nutter@sun.com>
>
> Robert Klemme wrote:
>>
>> We always need to balance cost and benefit.  In this case to me the
>> benefit seems to be outweighed by costs whereas the other change can
>> have an impact on readability.  YMMV though.
>
> The cost isn't high. 15 minutes of work in JRuby, probably more in CRuby but not by a 
lot.

That's likely only implementation.  Then there is testing,
documentation and before that checking that there are no negative
effects of the change.  If there are - and there seems to be evidence
that this is the case in Mark's posting - those negative effects also
count as costs...

Kind regards

robert
Ede2aa10c6462f1d825143879be59e38?d=identicon&s=25 Charles Oliver Nutter (Guest)
on 2009-05-14 16:04
(Received via mailing list)
Robert Klemme wrote:
> That's likely only implementation.  Then there is testing,
> documentation and before that checking that there are no negative
> effects of the change.  If there are - and there seems to be evidence
> that this is the case in Mark's posting - those negative effects also
> count as costs...

Bah, I say.

~/projects/jruby âž” jruby -X-C -e '[1,2,3].each {puts $it}'
1
2
3

Diff follows.

diff --git a/src/org/jruby/RubyGlobal.java
b/src/org/jruby/RubyGlobal.java
index f25bd42..c107a7b 100644
--- a/src/org/jruby/RubyGlobal.java
+++ b/src/org/jruby/RubyGlobal.java
@@ -199,6 +199,7 @@ public class RubyGlobal {

          runtime.defineVariable(new ErrorInfoGlobalVariable(runtime,
"$!", runtime.getNil()));
          runtime.defineVariable(new NonEffectiveGlobalVariable(runtime,
"$=", runtime.getFalse()));
+        runtime.defineVariable(new ImplicitItGlobalVariable(runtime,
"$it"));

          if(runtime.getInstanceConfig().getInputFieldSeparator() ==
null) {
              runtime.defineVariable(new GlobalVariable(runtime, "$;",
runtime.getNil()));
@@ -320,6 +321,24 @@ public class RubyGlobal {
          }
      }

+    private static class ImplicitItGlobalVariable extends
GlobalVariable {
+        public ImplicitItGlobalVariable(Ruby runtime, String name) {
+            super(runtime, name, null);
+        }
+
+        @Override
+        public IRubyObject set(IRubyObject value) {
+            return
runtime.getCurrentContext().getCurrentScope().setImplicitArg(value);
+        }
+
+        @Override
+        public IRubyObject get() {
+            IRubyObject obj =
runtime.getCurrentContext().getCurrentScope().getImplicitArg();
+            if (obj == null) obj = runtime.getNil();
+            return obj;
+        }
+    }
+
      private static class LastExitStatusVariable extends GlobalVariable
{
          public LastExitStatusVariable(Ruby runtime, String name) {
              super(runtime, name, runtime.getNil());
diff --git a/src/org/jruby/runtime/DynamicScope.java
b/src/org/jruby/runtime/DynamicScope.java
index e2f6e90..9ad9deb 100644
--- a/src/org/jruby/runtime/DynamicScope.java
+++ b/src/org/jruby/runtime/DynamicScope.java
@@ -39,6 +39,8 @@ public abstract class DynamicScope {
      // been called.
      protected DynamicScope evalScope;

+    protected IRubyObject implicitArg;
+
      protected DynamicScope(StaticScope staticScope, DynamicScope
parent) {
          this.staticScope = staticScope;
          this.parent = parent;
@@ -165,6 +167,14 @@ public abstract class DynamicScope {
          return staticScope.getAllNamesInScope();
      }

+    public IRubyObject getImplicitArg() {
+        return implicitArg;
+    }
+
+    public IRubyObject setImplicitArg(IRubyObject implicitArg) {
+        return this.implicitArg = implicitArg;
+    }
+
      /**
       * Get backref
       */
diff --git a/src/org/jruby/runtime/InterpretedBlock.java
b/src/org/jruby/runtime/InterpretedBlock.java
index 8015be8..4291066 100644
--- a/src/org/jruby/runtime/InterpretedBlock.java
+++ b/src/org/jruby/runtime/InterpretedBlock.java
@@ -162,6 +162,7 @@ public class InterpretedBlock extends BlockBody {
          Frame lastFrame = pre(context, null, binding);

          try {
+            context.getCurrentScope().setImplicitArg(value);
              if (hasVarNode) {
                  setupBlockArg(context, varNode, value, self);
              }
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2009-05-14 16:47
(Received via mailing list)
On Thu, May 14, 2009 at 11:33 AM, Lars Christensen
<larschbelunktumdk@gmail.com> wrote:
> as the default name for block parameters:
>
>   arr.sort_by { $_.size }
>   File.open("logfile", "a") { $_.puts logtext }
>   arr.map { foo2bar($_) }
>
> Then I remember how people abuse it and avoid using appropriately
> named variables, and I am again happy about the little extra code I
> have to write.
>
>
Forget the $ and you are spelling out a thought I was bearing with me
for quite some time, ty Daniel and Joel to bring this up :).
I always wanted an implicit _ parameter in blocks, as e.g.
3.times do puts _ end





--
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, préparer des
outils, répartir les tâches, alléger le travail… mais enseigne aux
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect
wood and don’t assign them tasks and work, but rather teach them to
long for the endless immensity of the sea.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2009-05-14 18:42
(Received via mailing list)
Mark Thomas wrote:
> config "my window" do
>    .width calculate_width
>    .height @y
> end
>
> Now how does the parser know what .height refers to: calculate_width,
> or the implicit block variable?

Yeah, seems impossible. Maybe if there were some other character instead
of "." to signify sending a message to the block's "default object".
Ba91caa4b1fd66471e4180151b379dd7?d=identicon&s=25 Jörg W Mittag (Guest)
on 2009-05-15 00:30
(Received via mailing list)
Daniel DeLorme wrote:
> Gregory Brown wrote:
>> On Thu, May 14, 2009 at 12:16 AM, Daniel DeLorme <dan-ml@dan42.com> wrote:
>>> Well, you never know... Matz *did* add the Symbol#to_proc conversion in
>>> 1.9 and also the foo\n.bar "fluent interface" syntax. So apparently
>>> trivial changes *do* make their way into core... sometimes.
>> But Symbol#to_proc is not a parser change. It's just using an existing
>> hook that has been around in Ruby 1.8
> But the fluent interface change *is* a parser change. My point was just
> that seemingly trivial requests *can* make it into the core, whether
> they're a syntax change or not.

Was that fluent interface syntax really a request? I cannot remember
anyone asking for it. I do, however, vividly recall various petitions
to *remove* that change.

jwm
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (djberg96)
on 2009-05-15 00:31
(Received via mailing list)
On May 13, 8:42 pm, Daniel DeLorme <dan...@dan42.com> wrote:
> It seems that often an object will be passed into a block only to invoke
> a method of that object:
>    arr.map{ |obj| obj.some_method }
>
> So I had the (weird? stupid?) thought that it would be nice to have some
> syntactic sugar like this:
>    arr.map{ .some_method }

require 'enumerable/extra'

arr.map(:some_method)

Regards,

Dan
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2009-05-15 02:06
(Received via mailing list)
Mmm losing the $ would then render RSpec completely inoperable since
it has an it method.

--Jeremy

On Thu, May 14, 2009 at 9:46 AM, Robert Dober <robert.dober@gmail.com>
wrote:
>>
>>
> --
> Antoine de Saint-Exupéry
>
>



--
http://jeremymcanally.com/
http://entp.com/
http://omgbloglol.com

My books:
http://manning.com/mcanally/
http://humblelittlerubybook.com/ (FREE!)
134ea397777886d6f0aa992672a50eaa?d=identicon&s=25 Mark Thomas (Guest)
on 2009-05-15 02:45
(Received via mailing list)
On May 14, 6:31 pm, Daniel Berger <djber...@gmail.com> wrote:
> require 'enumerable/extra'
>
> arr.map(:some_method)
>
> Regards,
>
> Dan

Cool! What would it take to make this 1.9 compatible?
This topic is locked and can not be replied to.