ruby picture

RCR 274: Required Block Argument

Submitted by transami (Sun Aug 08 17:08:29 UTC 2004)

Abstract

In Ruby one uses constructs that *in effect* take a required block without using the keyword do. For example:


    
  class
    ...
  end
  def
    ...
  end
  if
    ...
  end

    

It would be really nice to be able to define new methods that can do this too.

Problem

A lack of conistancy with some of the built in statements, but more importantly the inability to create methods that take a mandetory block (w/o extra error checking) as well as not require a do statement.

Proposal

Using &block argument should make it a required argument, like other arguments. In which case the do statement is not needed. For example:

def mymeth(&b)
  b.call
end

  1. no do
mymeth
  puts 'hi'
end

To make the block optional, yet still named use an default argument of either nil or &{} (for empty proc), depending:

def mymeth(&b=nil)
  ...

-OR-
def mymeth(&b=&{})
  ...

    

Analysis

This would allow for nicer looking code, and be more congruent with other parts of the sytax like class, module and def. In fact those would now have the *potential* of becoming bonofide methods too.

Implementation

There could be some compatability problems with methods that already take an *optional*, *named* block. But, those seem to be the rarest sort, and it would just mean adding the =nil or what have you.
ruby picture
Comments Current voting

About omitting "do":

I don't think yacc will accept syntax to allow block without starting punctuation. "class", "def", "module" etc. are keywords, so that the parser knows they always take code fragment, whereas "mymethods" is a mere identifier that the parser is impossible to know whether it takes block or not. Note that "def" statement is not evaluated at the time of compilation AND there's no information of applicable method to the parser due to the polymorphism.

About methods with mandatory blocks:

Maybe a good idea, but proposed syntax has compatibility issue. I can't take this.

-- matz.


If your going to vote *strongly*, please provide a comment. Thanks.


Comments are optional, and I hadn't really wanted to say anything, but I'm willing to if you want.

I think this idea addresses no existing problem, and the proposed solution produces extremely unclear code. When I see:

  mymeth
    puts "hi"

what I see is a variable or method call, followed by a call to puts. How am I supposed to know this is a block -- and why is this an improvement over *telling* me that it's a block? (Before I read ahead and encounter 'end', that is.)

The only answer I can think of is significant indenting, Python-style (i.e., the fact that "puts" is indented means it's a code block), which I dislike.

The analogy with keywords like 'class' and 'def' is off the mark, I fear. It's not a good idea to have every method name automatically act like a keyword.

If your method requires a block, and doesn't get one, an exception will be raised when it tries to call the block (and if it doesn't try to call it, it presumably has no reason to require it). So the missing 'do' is cryptic, and the basic idea of requiring a block is unnecessary.

-- David Black


I like the idea of being able to define things that look like Ruby language structures. I don't know how useful this is, but I like it nonetheless.

This RCR as it stands, though, has several major problems. Methods are defined at run-time, but determining where the end of the block is happens at compile time. Consider this code:

  foo
    puts 1
  end

By itself it looks like you might be calling foo with a block, and that you simply omitted the do, but I have fooled you (or at least tried). This is really just poorly indented, and it's in fact an excerpt from a piece of code that looks like this:

  def bar
  foo
    puts 1
  end

The parser cannot know whether foo takes a block without a do until foo has been defined, but that definition doesn't happen at parse-time. The parser, then, doesn't know whether the end goes with foo or whether the end goes with def bar. (It could potentially use some heuristics, but I suspect that this wouldn't work very well and would only make the parser more complex).

This would also wreak havoc with most editors' smart indenting.

Also, what would you do with:

  class Foo
    def foo(&block); end
  end
  class Bar
    def foo(); end
  end
  def bar(obj)
    obj.foo
      puts 42
    end
  end

Here we don't know whether obj.foo takes do-style (i.e. Bar#foo) or no-do-style (Foo#foo).

I think the intent behind this RCR is a good one (making the parser less complex by reducing the number of keywords), but is just not well thought-out. IMO you should definitely resubmit this RCR when you have a good, self-consistent, well-written solution that does not make the parser more complex.

-- Paul Brannan


Thanks for the critiques. I see the source of the problem. The parser would need the method definitions, but they aren't available until some time after the parser has already done its job. I guess there's no way around this. It is too bad, defining one's own keywords, as it were, would have given Ruby greater flexability.

Case in point, and the personal reason I requested this, is that I am going to do a test implemention of my AOP RCR, which requires something akin to a class structure. I can do it with a method, but ideally I'd want to get rid of the do.

So now I'm sort-of wishing class, def, if, etc. used do as well. Then this would never had occured to me. But I admit I'm a bit over-the-top when it comes to syntax symmetries ;)

-- trans.


I thought about this a bit more and it seems to me that the incompatability caused with the Required Block would actually be rather slight becasue it is so easily recognized and fixed. And it could be phased in, at first only giving a warning.

On the other front, could ruby have a Kernel#keyword method for defining new keywords? What are the implications of this?

-- trans.


Kernel#keyword (or define_keyword maybe) has several serious problems:

  • the method is executed in run time, which is too late for script compilation.
  • adding keyword on the fly makes syntax too fragile. it is as bad as macros in the language with usual syntax.

I think you'd better to ponder about the timing between compile time and run time.

-- matz.


I see --still much the same difficulties. Thanks for all the input. I'll cancel this RCR now.

Sorry, if this RCR seemed poorly thought out. I'm not largely familiar with the implementation of programming languages. I'm still learning a great deal on this end of things. I was really coming at this RCR from an end-user's standpoint.

-- trans.


Strongly opposed 4
Opposed 1
Neutral 0
In favor 0
Strongly advocate 1
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .