Pythonic indentation (or: beating a dead horse)

I didn't accidentally illustrate anything. And everything has a
cost. Why don't you list for yourself the cost of editing code with
significant white space?
Maybe for you, those costs are irrelevant. For me, the costs of ends
in Ruby code are irrelevant.

But your point was about *readability* not maintainability. I don't
think that good project organization is a 'cost' to readability.

···

On Wed, May 20, 2009 at 4:32 PM, Juan Zanos <juan_zanos@talkhouse.com> wrote:

You want me to have even more files and spend even more time folding and
unfolding things. And you assume I use a crummy editor and there is a
better one that magically makes a surprising number of wasted lines
irrelevant. I think you accidentally illustrated that extra lines have a
cost.

I still think this is a straw man. I'm rarely concerned with the
'readability' of a whole page of code.
I feel like there is something wrong with my design when I have to
think at that level.

For what it's worth, I actually can care less whether whitespace is
significant or not. Significant whitespace doesn't bother me in Haml.
The lack of significant whitespace doesn't bother me in Ruby.

What does bother me is that people somehow think this issue is so
important and dire, yet they think it's someone else's job to fix it.
If you want Ruby with significant whitespace, build it. Don't try to
convince folks who don't care about the issue.

-greg

···

On Wed, May 20, 2009 at 4:40 PM, Ryo Furue <furue@hawaii.edu> wrote:

On May 20, 9:50 am, Gregory Brown <gregory.t.br...@gmail.com> wrote:

Rick's point remains. If this is an issue you're facing, get a better editor.

But, the amount of meaningful code displayed in a single screenshot
still suffers. A screenful is a chunk of code
you can see without scrolling or jumping. The more meaning it
contains, the better you understand the code (as long as the meaning
is cleanly laid out, of course).

The Ant XML example is a bit ironic. Ant's creator regrets using XML. He believes that he should have used a scripting language instead. Take a look at Rake and you'll see a DSL that does what Ant does and more.

···

On May 21, 2009, at 1:26 PM, Steven Arnold wrote:

On May 21, 2009, at 8:06 AM, Roger Pack wrote:

Interesting--it's been awhile since I used C...what would
macros...essentially do? An example of them?

I was thinking more like Lisp macros. Check out:

   defmacro - The Nature of Lisp

steven

Me too. It's interesting how seemingly small changes can generate a lot of unexpected corner cases and unforeseen consequences. Of course, one could argue that using indentation does not preclude using explicit blocks in the same file. I doubt, for example, that anyone wishing to remove the 'end' keyword would wish to disallow something like:

     array_of_strings_that_are_numbers.sort! {|a,b| a.to_i <=> b.to_i}

...even though the {} brackets are the same as do..end.

If explicit blocks were allowed in the same file where blocks were, by default, determined by indentation, then you could have your cake and eat it too in the example above.

Nevertheless, I think your gut feel is correct......this would be a tricky thing to do right.

steven

···

On May 21, 2009, at 10:24 PM, Tony Arcieri wrote:

Quite frequently I do something like:

str = [a, b, c].map do |x|
thing1 = do_something_to x
thing2 = do_something_else_to x
"#{thing1}:#{thing2}"
end.join(",")

Reid Thompson wrote:

James Britt wrote:

I've wondered if this sort thing is a problem in Python; perhaps it is less likely there that any accidental indent or out-dent will still give you well-formed code.

I've only minimally looked at python, but I'm pretty sure that it will throw an error when indentation is fouled.

Sure, if in fact the indentation is fouled.

My concern is that you can mistakenly add 4 spaces instead of two, or vice versa, and get valid code (i.e. the parser does not see anything technically wrong) yet not have the code you really wanted.

James

Finally, I thought, an example! Time to dig out that old Ruby script

for preprocessing Python-style Ruby files... ah, there it is, on the
old MacBook Pro... copy it over to the current computer... hmm, no
doc... throw in a few quick and dirty patches to make it run; after
all, this is just a proof-of-concept, right? Edit the file, remove the
'end's and insert colons after the keywords which began those blocks,
run it through and... hey, whaddaya know, [16, 22, 28], first time
through. Looks like ol' Tony really _was_ talking out of his ass, eh?

You accomplished ABSOLUTELY nothing with your magic trick here, and you darn
well know it. You in no way shape or form made the indent context work at
all. All you did was figure out that a regular expression could add the word
"end" to a block of data when told to. No one ever said that wasn't
possible. That would be like saying that python can actually handle multi
line lambdas if I took your same concept and pre-processed a file to take
any multi line lambdas and convert them to a function which is called as a
single line lambda. So are you now saying that anyone that claims the python
engine doesn't handle multi-line lambdas is talking out of their ass?

If all you want is a preprocessor then it seems like you already have what
you want and can be on your way to writing what you perceive as beautiful
code immediately. Congrats and have at it, I'm not sure what more you would
want at this point.

If you feel that you want to push this further into the core then again -
have at it - many folks have suggested that forking and getting some ACTUAL
working code in front of folks is the surest way to get things accomplished!
I doubt that anyone would truly object if you implemented what you suggest,
they simply are of the mindset that it won't work - prove them wrong, and
not with a magic trick either.

Best of luck to you!

John W Higgins

···

On Mon, May 25, 2009 at 9:40 AM, J Haas <Myrdred@gmail.com> wrote:

It's certainly not impossible, as the script you posted shows. That
script is a hack, however, since it doesn't lex its input properly and
it will fail in obscure cases. I've written a proper implementation,
based on my RubyLexer library.

Basically, it makes the end keyword optional. If you leave off the
end, the preprocessor inserts an end for you at the next line indented
at or below the level of indentation of the line which started the scope.

End is optional, so you can still write things like this:
  begin
    do_something
  end until done?
(However, you'd better make damn sure you get the end indented to the
right level!)

This script uses RubyLexer to extract a stream of tokens and modify
it, then turn those tokens back into ruby code. Since RubyLexer is a
complete stand-alone lexer, this should be a very thorough solution,
free of insoluable little problems due to the script's inability to
follow where comments and strings start and stop. (That said, I'm sure
there will be some problems with it, as it's pretty raw code.)

As different programs have a variety of interpretations as to the
width of a tab character, tabs for indentation are absolutely
forbidden by endless.rb.

If you're interested, please see:

···

On 5/25/09, J Haas <Myrdred@gmail.com> wrote:

Now, having said all that: I do not _know_ that Tony's claim is false.
As I said, I was surprised to be told that my proposal was impossible
and I lack the theoretical background to prove otherwise. So if anyone
out there agrees with Tony that Pythonic indentation in Ruby would not
be merely ill-advised but _impossible_ I'd appreciate an example. Then
I can stop wasting my time.

As I said, I was surprised to be told that my proposal was impossible
and I lack the theoretical background to prove otherwise. So if anyone
out there agrees with Tony that Pythonic indentation in Ruby would not
be merely ill-advised but _impossible_ I'd appreciate an example. Then
I can stop wasting my time.

I was on a questionable connection at the time, so my original message may not have gotten to the mailing list:

> cat impossible.rb

# This one can't be done in Pythonic style:

result = case ARGV[0]
   when /^\d*$/
     "That's an integer!"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word."
   end if ARGV[0]

puts result if result

Cheers,

Josh

···

On May 25, 2009, at 9:40 AM, J Haas wrote:

I find this code less readable than the above original code with the
'end's included

···

On Thu, May 28, 2009 at 01:35:11AM +0900, J Haas wrote:

On May 22, 9:01 am, Roger Pack <rogerpack2...@gmail.com> wrote:
> Tony's point was that certain constructs, like case statements, won't be
> transformable into indentation only blocks. Does that make sense?

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

Code speaks louder than words, right? Here's some real-world code...
it's application_controller.rb from the AuthLogic example (http://
github.com/binarylogic/authlogic_example/tree):

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
  helper :all
  helper_method :current_user_session, :current_user
  filter_parameter_logging :password, :password_confirmation

  private
    def current_user_session
      return @current_user_session if defined?(@current_user_session)
      @current_user_session = UserSession.find
    end

    def current_user
      return @current_user if defined?(@current_user)
      @current_user = current_user_session &&
current_user_session.record
    end

    def require_user
      unless current_user
        store_location
        flash[:notice] = "You must be logged in to access this page"
        redirect_to new_user_session_url
        return false
      end
    end

    def require_no_user
      if current_user
        store_location
        flash[:notice] = "You must be logged out to access this page"
        redirect_to account_url
        return false
      end
    end

    def store_location
      session[:return_to] = request.request_uri
    end

    def redirect_back_or_default(default)
      redirect_to(session[:return_to] || default)
      session[:return_to] = nil
    end
end

-----------------

Nothing particularly special about this code, right? Pretty standard
Ruby, if a bit simple? 37 non-blank, non-comment lines, of which 9
consist of the bare word "end". I defy anyone to tell me that the code
would be less readable as this:

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
  helper :all
  helper_method :current_user_session, :current_user
  filter_parameter_logging :password, :password_confirmation

  private
    def current_user_session:
      return @current_user_session if defined?(@current_user_session)
      @current_user_session = UserSession.find

    def current_user:
      return @current_user if defined?(@current_user)
      @current_user = current_user_session &&
current_user_session.record

    def require_user:
      unless current_user:
        store_location
        flash[:notice] = "You must be logged in to access this page"
        redirect_to new_user_session_url
        return false

    def require_no_user:
      if current_user:
        store_location
        flash[:notice] = "You must be logged out to access this page"
        redirect_to account_url
        return false

    def store_location:
      session[:return_to] = request.request_uri

    def redirect_back_or_default(default):
      redirect_to(session[:return_to] || default)
      session[:return_to] = nil

I'm just going to stick my head out for a second and say that I think the
first code was more readable, with the end blocks. I LIKE being able to
clearly see the end of a logical block. Yes, I can see the indentation
change, but having a keyword end sections of code does a few things:
1. It's easier for me to read, especially if I'm just skimming through
2. It's easier to parse, and makes for cleaner parser code (to me, at least)

Come on guys, it's only 3 characters. Pythonic indentation is a big debate
among programming languages, so can't we just accept it how it is and move
on? Or, if someone really wants to change it, fork ruby and make the change
yourself. Put up or shut up, is my (probably unwanted) opinion on the
subject.

Alex

···

On Wed, May 27, 2009 at 12:35 PM, J Haas <Myrdred@gmail.com> wrote:

On May 22, 9:01 am, Roger Pack <rogerpack2...@gmail.com> wrote:
> Tony's point was that certain constructs, like case statements, won't be
> transformable into indentation only blocks. Does that make sense?

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

Code speaks louder than words, right? Here's some real-world code...
it's application_controller.rb from the AuthLogic example (http://
github.com/binarylogic/authlogic_example/tree):

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation

private
   def current_user_session
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find
   end

   def current_user
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record
   end

   def require_user
     unless current_user
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false
     end
   end

   def require_no_user
     if current_user
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false
     end
   end

   def store_location
     session[:return_to] = request.request_uri
   end

   def redirect_back_or_default(default)
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil
   end
end

-----------------

Nothing particularly special about this code, right? Pretty standard
Ruby, if a bit simple? 37 non-blank, non-comment lines, of which 9
consist of the bare word "end". I defy anyone to tell me that the code
would be less readable as this:

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation

private
   def current_user_session:
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find

   def current_user:
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record

   def require_user:
     unless current_user:
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false

   def require_no_user:
     if current_user:
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false

   def store_location:
     session[:return_to] = request.request_uri

   def redirect_back_or_default(default):
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

True I suppose case statements could be done using blocks.
Note also that you don't "need" the ending : per line, either.

-=r

···

--
Posted via http://www.ruby-forum.com/\.

Tony's point was that certain constructs, like case statements, won't be
transformable into indentation only blocks. Does that make sense?

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

Ok, but now you're beginning to see the edge cases that make this sort of transformation difficult on a global level. Specifically, how would you differentiate between these two cases using Pythonic indentation:

> cat conditional_case.rb
result = case ARGV[0]
   when /^\d*$/
     "That's an integer"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word"
   end if ARGV[0]

puts result

> cat case_and_conditional.rb
result = case ARGV[0]
   when /^\d*$/
     "That's an integer"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word"
   end
if ARGV[0]
   puts result
end

Attaching a conditional to the end of a case statement (or any block, for that matter) is possible in Ruby because the block is just an expression, and the statement doesn't end until the newline. With your preprocessor, adding "end " when the indentation level decreases would yield the first form, but then how do I get the second form? I suppose I could both decrease the indentation level and leave a blank space, but then it seems like we're adding an awful lot of formatting rules just to have the code look nice and still function. On top of that, I think this makes things much less clear! Consider that in "Pythonic form" the above cases would become:

> cat pythonic_conditional_case.rb
result = case ARGV[0]:
   when /^\d*$/
     "That's an integer"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word"
if ARGV[0]
puts result

> cat pythonic_case_and_conditional.rb
result = case ARGV[0]:
   when /^\d*$/
     "That's an integer"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word"

if ARGV[0]:
   puts result

Looking at those two pieces of code, is it clear that they do two different things? At the very least, I think that this sort of change to the syntax would have to be optional. This would, of course, mean that you're not getting rid of all of the "end"s in code, so then what's the point (other than to confuse matters of syntax even more)?

Let me also provide a counter-point. I'm currently using MacVim with the ruby-vim files and a coloring scheme which colors "def...end" pairs in yellow and other "case/if/do/etc...end" pairs in purple. This gives me a good way to quickly look at some code, and if I see that the "end" immediately preceding a "def" is purple, then I know I've forgotten and "end" somewhere in that function definition.

Finally, let me suggest a bit of a "wisdom of crowds" argument: if the advantages to significant whitespace were so unambiguously clear as you'd have us believe, then why do most languages not use it (even those developed before many of the advantages of advanced text editors/IDEs existed)?

- Josh

···

On May 27, 2009, at 9:35 AM, J Haas wrote:

On May 22, 9:01 am, Roger Pack <rogerpack2...@gmail.com> wrote:

As I've watched this debate unfold I've watched the stronger criticisms fall
apart. The strongest type of criticism would be that it can't be done, or that
it's too hard to be done. But the impossible examples seem to be defeated
fairly easily. Moreover, the solutions are backward compatible to existing
Ruby.

Now when I look at this latest example I see some ordinary code that's 44 lines
long. With the pythonic scheme it looks like it's only 35 lines long. I find
it difficult to convince myself that it's a good idea to make code 25% larger
just to preserve some ends of dubious value.

I suppose I could try to come up with some nonsense argument that 'end' makes
everything more readable. But that would just be prejudice. The pythonic
example is trivially easy to read. It can't just be me. There seems to be no
shortage of Python folk who have no problem. Objectively, the ends just take
up a whole lot of space.

···

On May 27, 2009, at 12:35 PM, J Haas wrote:

On May 22, 9:01 am, Roger Pack <rogerpack2...@gmail.com> wrote:

Tony's point was that certain constructs, like case statements, won't be
transformable into indentation only blocks. Does that make sense?

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

Code speaks louder than words, right? Here's some real-world code...
it's application_controller.rb from the AuthLogic example (http://
github.com/binarylogic/authlogic_example/tree):

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user

On May 27, 2009, at 12:35 PM, J Haas wrote:

On May 22, 9:01 am, Roger Pack <rogerpack2...@gmail.com> wrote:

Tony's point was that certain constructs, like case statements, won't be
transformable into indentation only blocks. Does that make sense?

No, it doesn't, because I don't see why case statements are not
transformable into indent-only blocks. I've _done_ them using the
quick-and-dirty hacky script and they work just fine. (In cases like
Joshua's impossible.rb I had to make a minor modification to the
script to have it inject 'end ' rather than 'end\n', but it still
worked fine.)

Code speaks louder than words, right? Here's some real-world code...
it's application_controller.rb from the AuthLogic example (http://
github.com/binarylogic/authlogic_example/tree):

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation

private
   def current_user_session
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find
   end

   def current_user
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record
   end

   def require_user
     unless current_user
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false
     end
   end

   def require_no_user
     if current_user
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false
     end
   end

   def store_location
     session[:return_to] = request.request_uri
   end

   def redirect_back_or_default(default)
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil
   end
end

-----------------

Nothing particularly special about this code, right? Pretty standard
Ruby, if a bit simple? 37 non-blank, non-comment lines, of which 9
consist of the bare word "end". I defy anyone to tell me that the code
would be less readable as this:

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation

private
   def current_user_session:
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find

   def current_user:
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record

   def require_user:
     unless current_user:
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false

   def require_no_user:
     if current_user:
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false

   def store_location:
     session[:return_to] = request.request_uri

   def redirect_back_or_default(default):
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil

As this debate unfolds I've watched the stronger criticisms fall apart. The
strongest type of criticism would be that it can't be done, or that it's too
hard to do. But the impossible examples seem to be defeated fairly easily.
Moreover, the solutions are backward compatible to existing Ruby.

Now when I look at this latest example I see some ordinary code that's 44 lines
long. With the pythonic scheme it looks like it's only 35 lines long. I find
it difficult to convince myself that it's a good idea to make code 25% larger
just to preserve some ends of dubious value.

I suppose I could try to come up with some nonsense argument that 'end' makes
everything more readable. But that would just be prejudice. It's trivially
easy to read. It can't just be me. There seems to be no shortage of Python
folk who have no problem either. Objectively, being forced to explicitly type
'end' all the time seems to takes up a whole lot of space.

filter_parameter_logging :password, :password_confirmation

private
   def current_user_session
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find
   end

   def current_user
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record
   end

   def require_user
     unless current_user
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false
     end
   end

   def require_no_user
     if current_user
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false
     end
   end

   def store_location
     session[:return_to] = request.request_uri
   end

   def redirect_back_or_default(default)
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil
   end
end

-----------------

Nothing particularly special about this code, right? Pretty standard
Ruby, if a bit simple? 37 non-blank, non-comment lines, of which 9
consist of the bare word "end". I defy anyone to tell me that the code
would be less readable as this:

-----------------

# Filters added to this controller apply to all controllers in the
application.
# Likewise, all the methods added will be available for all
controllers.

class ApplicationController < ActionController::Base
helper :all
helper_method :current_user_session, :current_user
filter_parameter_logging :password, :password_confirmation

private
   def current_user_session:
     return @current_user_session if defined?(@current_user_session)
     @current_user_session = UserSession.find

   def current_user:
     return @current_user if defined?(@current_user)
     @current_user = current_user_session &&
current_user_session.record

   def require_user:
     unless current_user:
       store_location
       flash[:notice] = "You must be logged in to access this page"
       redirect_to new_user_session_url
       return false

   def require_no_user:
     if current_user:
       store_location
       flash[:notice] = "You must be logged out to access this page"
       redirect_to account_url
       return false

   def store_location:
     session[:return_to] = request.request_uri

   def redirect_back_or_default(default):
     redirect_to(session[:return_to] || default)
     session[:return_to] = nil

I'm saying that when all other factors are held constant more lines is
less readable. Your arguments ignore that and only place value on
editors and project management when the extra lines exist and
not when they don't. That's not a level playing field.

Thinking about ways to reduce this overhead in the language is good.

···

On May 20, 2009, at 4:39 PM, Gregory Brown wrote:

On Wed, May 20, 2009 at 4:32 PM, Juan Zanos > <juan_zanos@talkhouse.com> wrote:

You want me to have even more files and spend even more time folding and
unfolding things. And you assume I use a crummy editor and there is a
better one that magically makes a surprising number of wasted lines
irrelevant. I think you accidentally illustrated that extra lines have a
cost.

I didn't accidentally illustrate anything. And everything has a
cost. Why don't you list for yourself the cost of editing code with
significant white space?
Maybe for you, those costs are irrelevant. For me, the costs of ends
in Ruby code are irrelevant.

But your point was about *readability* not maintainability. I don't
think that good project organization is a 'cost' to readability.

Juan Zanos wrote:

···

On May 21, 2009, at 1:26 PM, Steven Arnold wrote:

On May 21, 2009, at 8:06 AM, Roger Pack wrote:

Interesting--it's been awhile since I used C...what would
macros...essentially do? An example of them?

I was thinking more like Lisp macros. Check out:

   defmacro - The Nature of Lisp

The Ant XML example is a bit ironic. Ant's creator regrets using
XML. He believes that he should have used a scripting language
instead. Take a look at Rake and you'll see a DSL that does what Ant
does and more.

JDD actually not only regrets using XML for Ant, he eclusively uses
Rake now to build his Java projects. At least that's what I read,
anyway.

jwm

My concern is that you can mistakenly add 4 spaces instead of two, or vice versa, and get valid code (i.e. the parser does not see anything technically wrong) yet not have the code you really wanted.

That happened to us a couple times developing in
Python. We were using spaces only (no tabs) ...
but somehow some tab characters did occasionally
sneak into a source file. (Possibly by copy/paste
of code from a different editor--I was never sure
how it happened.)

So the indentation looked fine to us in the editor
(seeing two-column tabs), but was interpreted
differently by Python (eight-column tabs), resulting
in some baffling "it can't possibly be doing that!"
moments while debugging.

These days, I have my editor set to highlight tab
characters visually... :slight_smile:

Regards,

Bill

···

From: "James Britt" <james.britt@gmail.com>

You can get the same problem by misplacing a bracket or a paren. The only
difference I see is that the indentation is a lot more visibly obvious.

···

On Sunday 24 May 2009 03:42:19 pm James Britt wrote:

My concern is that you can mistakenly add 4 spaces instead of two, or
vice versa, and get valid code (i.e. the parser does not see anything
technically wrong) yet not have the code you really wanted.

Yes, and it's this very sort of case that led me to make end optional
rather than forbidden in endless.rb. Clearly, some things can't be
expressed just in pythonish syntax, so you have to be able to drop
back to ruby mode. The need for more tokens on the same line after the
end is sufficiently rare that I don't think it detracts from the
overall effect; almost all ends can still be eliminated.

Actually, I think pyrb.rb also will tolerate this example as well; you
just leave off the colon and it doesn't expect to create an end for
you for that statement. Looks like it's missing the 'when' special
case, but for this example, that doesn't matter, since you have the
whens more indented anyway.

···

On 5/25/09, Joshua Ballanco <jballanc@gmail.com> wrote:

I was on a questionable connection at the time, so my original message
may not have gotten to the mailing list:

> cat impossible.rb

# This one can't be done in Pythonic style:

result = case ARGV[0]
   when /^\d*$/
     "That's an integer!"
   when /^[A-Za-z]*$/
     "That looks like a word..."
   else
     "That's not an integer or a word."
   end if ARGV[0]

puts result if result

This script uses RubyLexer to extract a stream of tokens and modify
it, then turn those tokens back into ruby code. Since RubyLexer is a
complete stand-alone lexer, this should be a very thorough solution,
free of insoluable little problems due to the script's inability to
follow where comments and strings start and stop. (That said, I'm sure
there will be some problems with it, as it's pretty raw code.)

As different programs have a variety of interpretations as to the
width of a tab character, tabs for indentation are absolutely
forbidden by endless.rb.

If you're interested, please see:
endless.rb · GitHub

Could you post us a few examples of what code formatted this way looks
like (or must look like)? I assume it handles here documents well?

The italics part of that gist is somewhat hard to read :slight_smile:

@Michael:
I don't think having "either or" syntax would be such a terrible thing
in terms of team re-use or resources--you should be able to convert the
code back and forth at will (a la ruby2ruby, parsetree [rubylexer has a
parsetree compatibility mode] etc.)
Cheers!
-=r

···

--
Posted via http://www.ruby-forum.com/\.

+1 - the significant white space is one of several reasons I've never managed to get comfy with python.

Personally I like 'end' because it makes it explicitly clear that the programmer's intent was to end a block at that point, and I've wasted enough of my life tracking down nesting errors not to want to give up that extra bit of insight. If other people feel differently, well it's there code and they're free to do as they please with it so long as I'm not expected to maintain it.

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

···

On 27 May 2009, at 17:41, Reid Thompson wrote:

I find this code less readable than the above original code with the
'end's included

----
raise ArgumentError unless @reality.responds_to? :reason