What about allowing to specify, which end belongs to which start?

Hi Ruby mailing list,

I’ve recently come across a pretty common situation in Ruby:

   end
 end

end

After those parts, you often don’t know, where exactly you have to
continue.

So what about allowing to specify, which end belongs to which start?
I’ve thought about something like this:

   end|do
 end|if

end|def

or

   end~do
 end~if

end~def

or

   end:do
 end:if

end:def

If you specify it, and it does not match, the compiler throws an error.
Of course, you can always omit it to have the normal behaviour, but you
are encouraged to often “document”, which end belongs to which block
(and you do yourself a favour in these nested situations).

What do you think about it?

On Jul 9, 2010, at 12:05 , Jan L. wrote:

I’ve thought about something like this:

What do you think about it?

I think if you have so many ends that you need to extend the syntax then
you’re doing something wrong to begin with (no pun). I try to make all
my methods short when I can, and I use judicious use of extra returns to
separate code into paragraphs to further help. I think this type of
syntax extension would further encourage large bad codes.

On 09.07.2010 21:17, Ryan D. wrote:

So what about allowing to specify, which end belongs to which
end:do end:if end:def
Not to forget about end:case, end:class, end:module…

If you specify it, and it does not match, the compiler throws an
error. Of course, you can always omit it to have the normal

The compiler as it is today will throw an error anyway.

behaviour, but you are encouraged to often “document”, which end
belongs to which block (and you do yourself a favour in these
nested situations).

I think “encouraged” is the wrong word. Your extension would force
the user to use this idiom (which I personally find too verbose). Also,
your solution does not help if you nest the same type of control flow
statement. If you want to document nesting you can do that today
already (and some people actually do it). But I agree with Ryan here:

What do you think about it?

I think if you have so many ends that you need to extend the syntax
then you’re doing something wrong to begin with (no pun). I try to
make all my methods short when I can, and I use judicious use of
extra returns to separate code into paragraphs to further help. I
think this type of syntax extension would further encourage large bad
codes.

Plus, editors with auto indentation and code completion usually help. I
personally have made it a habit to always write the opening and closing
construct before I fill in the body. That way you can work pretty well
even if your editor does not have fancy features.

Kind regards

robert

I think “encouraged” is the wrong word. Your extension would force
the user to use this idiom (which I personally find too verbose).
Also,
your solution does not help if you nest the same type of control flow
statement. If you want to document nesting you can do that today
already (and some people actually do it). […]

I thought more of: use it seldom (it’s too verbose), only at spots,
where there are, e.g. at least 3 "end"s… The problem with documenting
is that the interpreter cannot detect false order, etc.

I think if you have so many ends that you need to extend the syntax
then you’re doing something wrong to begin with (no pun). I try to
make all my methods short when I can, and I use judicious use of
extra returns to separate code into paragraphs to further help. I
think this type of syntax extension would further encourage large bad
codes.

Yes, the syntax would to have be extended… but that’s no reason why it
cannot be good…
Unfortunately, it is not always possible (or good) to keep the code
short and flat…

Plus, editors with auto indentation and code completion usually help.
I
personally have made it a habit to always write the opening and
closing
construct before I fill in the body. That way you can work pretty
well
even if your editor does not have fancy features.

Yes, but it is not only about the writing, also about the reading or
refactoring of code.


J-_-L

On Jul 9, 2010, at 5:42 PM, Jan L. [email protected] wrote:

Unfortunately, it is not always possible (or good) to keep the code
short and flat…

Wrong wrong wrong. I cannot disagree more.

On Sat, 2010-07-10 at 14:45 +0900, Ryan D. wrote:

On Jul 9, 2010, at 5:42 PM, Jan L. [email protected] wrote:

Unfortunately, it is not always possible (or good) to keep the code
short and flat…

Wrong wrong wrong. I cannot disagree more.

I mean, of course, you should try to keep it short… but I think the

   end:do
 end:if

end:def

is not too much nested, in most cases. I do not want to put every block
or if into its own method…


J-_-L

On 7/9/10, Jan L. [email protected] wrote:

 end~if

end~def

or

   end:do
 end:if

end:def

I’ve been told that very old versions of ruby used to have this
feature, using a space to separate the end from the keyword being
terminated instead of | ~ or : as suggested by Jan. So, in other
words, you could write:

if foo
bar
end if

I like this syntax far above anything involving punctuation.
Supposedly, this feature was removed when the ‘modifier’ versions of
if and unless and etc were added to the language; keeping both was
difficult to support in the parser. However, after giving it a little
thought, it seems to me that a form of this feature could be
reintroduced with not an excessive amount of trouble. If the keyword
being terminated is immediately followed by a newline or semicolon, it
is treated as a Jan wants. Otherwise, it’s treated as a ‘modifier’
flow control (if it’s an if or unless or etc).

I could write a RubyLexer-based preprocessor which does this pretty
easily. However, I’m not terribly motivated. This doesn’t seem like
that useful a feature to me and I’ve got so much else to work on…

On 9 Jul 2010, at 20:05, Jan L. wrote:

If you specify it, and it does not match, the compiler throws an error.
Of course, you can always omit it to have the normal behaviour, but you
are encouraged to often “document”, which end belongs to which block
(and you do yourself a favour in these nested situations).

What do you think about it?

Jan, it’s not in Ruby’s nature to hold your hand so whilst I can’t see
any particular technical reason for having such an optional syntax
extension, I’d be uncomfortable with code that relied upon them.

In any event the underlying problem you’re describing is one which in
the vast majority of cases is a code smell and is best dealt with by
aggressive refactoring. Move the inner loops into their own method
calls, or write your outer-loop logics as a method taking a block and
drive iteration/whatever that way. The resulting code will be much
easier to read and maintain, and the generality will improve your code
reuse options.

Ellie

Eleanor McHugh
Games With Brains
http://feyeleanor.tel

raise ArgumentError unless @reality.responds_to? :reason

Jan L. wrote:

Hi Ruby mailing list,

I’ve recently come across a pretty common situation in Ruby:

   end
 end

end

After those parts, you often don’t know, where exactly you have to
continue.

You can always use comments, although I’d only usually do this for
nested modules. e.g.

module Foo
module Bar
class Baz

end # class Baz
end # module Bar
end # module Foo

Otherwise, I’ve never found it a problem, unless I’ve missed an ‘end’,
or forgotten a ‘do’.

ruby 1.9 with -w flag has a neat feature where it will warn if the
indentation is not as expected, thus making it much easier to find where
the problem is.

e.g.

$ cat test.rb
def foo
puts “hello”
5.times # note missing “do”
puts “world”
end
puts “goodbye”
end
$ ruby19 test.rb
test.rb:7: syntax error, unexpected keyword_end, expecting $end
$ ruby19 -w test.rb
test.rb:5: warning: mismatched indentations at ‘end’ with ‘def’ at 1
test.rb:7: syntax error, unexpected keyword_end, expecting $end

This shows that the ‘end’ at line 5 was associated with the ‘def’ at
line 1, which helps localise the problem.

It’s a shame that ruby 1.8.7 doesn’t have this feature, although you can
keep a copy of ruby 1.9 lying around just for locating such problems
(the parsing of the two languages is very similar, even though the
semantics are very different)

On 10.07.2010 17:54, Caleb C. wrote:

    end~do

feature, using a space to separate the end from the keyword being
if and unless and etc were added to the language; keeping both was
difficult to support in the parser.

I don’t want to advocate this but concatenating “end” directly with the
opening keyword is probably easy to do because it will create a whole
bunch of new tokens , so there would be

endclass
endmodule
enddef
endbegin
endif
endunless
endwhile
enduntil
endfor
enddo
endcase

Did I miss one?

Each of those would be then alternatively allowed to “end”, so you could
write

begin
if foo
else
case x
when y
when z
endcase
end
endbegin

I still don’t like it.

However, after giving it a little
thought, it seems to me that a form of this feature could be
reintroduced with not an excessive amount of trouble. If the keyword
being terminated is immediately followed by a newline or semicolon, it
is treated as a Jan wants. Otherwise, it’s treated as a ‘modifier’
flow control (if it’s an if or unless or etc).

IMHO this is not feasible: "if " is almost always followed by
a line break. And think about

begin
puts “aaa”
end if
x > 100

This is perfectly legal with the current syntax but it looks like “end
if” would be a terminator while in reality it is a statement modifier.

I could write a RubyLexer-based preprocessor which does this pretty
easily. However, I’m not terribly motivated. This doesn’t seem like
that useful a feature to me and I’ve got so much else to work on…

:slight_smile:

Cheers

robert

Thank you for all the opinions :slight_smile:

Robert wrote:

endcase

Did I miss one?

Each of those would be then alternatively allowed to “end”, so you
could
endbegin

I still don’t like it.

I agree, that does not look good. But with a little punctation, it
becomes more readable:

begin
if foo
else
case x
when y
when z
end~case
end
end~begin

Also compare the readability of the whole list with the token version:

end~class
end~module
end~def
end~begin
end~if
end~unless
end~while
end~until
end~for
end~do
end~case

The token version might be easier to implement, but I think, it is not
satisfying.

Caleb wrote:

I could write a RubyLexer-based preprocessor which does this pretty
easily. However, I’m not terribly motivated. This doesn’t seem like
that useful a feature to me and I’ve got so much else to work on…

Cool :). I also want to try to implement it in some way, but at the
earliest in about a month (also have too many things to do).

@Brian
Thank you for this neat 1.9 indention warning hint :slight_smile:

On 11.07.2010 13:37, Jan L. wrote:

enduntil
begin

I agree, that does not look good. But with a little punctation, it
becomes more readable:

… and much less typeable on my keyboard (German).

Also compare the readability of the whole list with the token version:
end~do
end~case

The token version might be easier to implement, but I think, it is not
satisfying.

The whole concept is dissatisfying to me. :slight_smile:

Kind regards

robert

On 11.07.2010 13:32, Caleb C. wrote:

endunless

thought, it seems to me that a form of this feature could be
reintroduced with not an excessive amount of trouble. If the keyword
being terminated is immediately followed by a newline or semicolon, it
is treated as a Jan wants. Otherwise, it’s treated as a ‘modifier’
flow control (if it’s an if or unless or etc).

IMHO this is not feasible: “if” is almost always followed by
a line break. And think about

Yes, but ‘if’ itself almost never is.

Unfortunately the word “almost” makes this unusable for creating a
parser. How do you want the parser to decide if the case at hand is one
of the rare cases? Even if it would be feasible this sounds like an
awful hack and I’d rather not make parsing more complicated (and thus
slower) as it is today.

I did consider this. Who ever writes this way, instead of putting the
‘if’ and condition on the same line? In cases like this, I think it
would be acceptable to break broken style.

Let’s hear what others say.

Kind regards

robert

On 7/11/10, Robert K. [email protected] wrote:

awful hack and I’d rather not make parsing more complicated (and thus
slower) as it is today.

The syntax change I proposed requires forbidding a construct which is
currently legal but rarely used and considered to be poor style. What
is wrong with that? In those few cases where someone decided to
separate an ‘if’ from its condition with a newline, the code would
have to be rewritten (inserting a backslash to make the newline soft
is the easiest way). Such constructs should be rewritten anyway, for
purely stylistic reasons.

This new feature, like most, will make the parser ever so slightly
slower. The delta is tiny and not worth mentioning.

And it will make the parser a little bit more complicated; however,
there are already many special cases and complications in the parser.
One more is not a big deal. The philosophy of ruby’s syntax overall is
to make the parser complicated if it makes life easier for the user. I
think this change at least ought to be considered under that
criterion.

Now if you want to argue that Jan’s proposal is esthetically
unpleasing, I won’t really disagree. But just leave it at that. I hate
it when people try to throw up a lot of rhetorical chaff when their
real, and only valid, objection amounts to a subjective judgment call.

On 7/11/10, Robert K. [email protected] wrote:

endwhile
enduntil
endfor
enddo
endcase

Eh, I don’t like it either.

However, after giving it a little
thought, it seems to me that a form of this feature could be
reintroduced with not an excessive amount of trouble. If the keyword
being terminated is immediately followed by a newline or semicolon, it
is treated as a Jan wants. Otherwise, it’s treated as a ‘modifier’
flow control (if it’s an if or unless or etc).

IMHO this is not feasible: "if " is almost always followed by
a line break. And think about

Yes, but ‘if’ itself almost never is. So when the parser sees ‘end’
followed by ‘if’ followed by newline, it can treat that specially.

begin
puts “aaa”
end if
x > 100

This is perfectly legal with the current syntax but it looks like “end
if” would be a terminator while in reality it is a statement modifier.

I did consider this. Who ever writes this way, instead of putting the
‘if’ and condition on the same line? In cases like this, I think it
would be acceptable to break broken style.

On 7/11/10, Jan L. [email protected] wrote:

Caleb wrote:

I could write a RubyLexer-based preprocessor which does this pretty
easily. However, I’m not terribly motivated. This doesn’t seem like
that useful a feature to me and I’ve got so much else to work on…

Cool :). I also want to try to implement it in some way, but at the
earliest in about a month (also have too many things to do).

If you want help figuring out how to do this, I’ll be glad to give you
advice, tho you’ll have to write it. Doing something like this the
right way is going to be quite difficult unless you know where to
start, and even after that will be fairly tricky. Unless you’re an
expert on parsing ruby, you need the assistance of someone (like me)
who is.

Of course, you could also do this the fragile/wrong way, using a lot
of regular expressions or something, in which case you’ll probably be
able to manage it on your own.

On 7/12/10, Robert K. [email protected] wrote:

it when people try to throw up a lot of rhetorical chaff when their
real, and only valid, objection amounts to a subjective judgment call.

It’s not only that. I question the balance of effort and benefit.
Since most code around does not use the new syntax, you will have to
support the old syntax as well. As long as it is not mandatory only

Well, it has to be optional for another reason too: it would be far to
annoying to have to type ‘end if’ instead of ‘end’ at the end of every
if statement. I for one wouldn’t be willing to sacrifice ruby’s
celebrated terseness in this area just to make Jan happy.

people benefit that use it. OTOH, there is additional effort for
backporting new code to projects that only use an old Ruby
interpreter. Given that we do not have this feature today and most
people seem to be able to write code that gets the nesting right I
wonder what the real benefit of this is given that there will be
development effort for the interpreter, test cases, documentation etc.

Uglyness was really just a side aspect although I agree I should have
made this more clear. Somehow I must have assumed that the other
points are obvious. :slight_smile:

I mostly agree apart from the missing aspect of efforts. Even such a
small change can cause significant other work to be done.

Ok, now this is a valid point, and one I tend to forget about.
Complicating code makes related work products more complicated but as
a single-minded engineer I only think about the code.

Additionally, I now see that there are some ambiguities around the
keyword ‘do’ which would have to be worked through before my proposal
could be implemented. So for example, this is valid currently:

something begin
42
end do
foo
end

But with the proposed new syntax, the ‘end do’ would be interpreted as
an attempt to end a do block. I’m not sure what, if anything, can be
done about this, or if it’s just an issue that can be ignored.

[…] I question the balance of effort and benefit.
Since most code around does not use the new syntax, you will have to
support the old syntax as well. As long as it is not mandatory only
people benefit that use it. OTOH, there is additional effort for
backporting new code to projects that only use an old Ruby
interpreter.

The backporting effort for 99% of the cases: code.gsub /end~(class|
module|def|begin|if|unless|while|until|for|do|case)/, ‘end’

Given that we do not have this feature today and most
people seem to be able to write code that gets the nesting right I
wonder what the real benefit of this is given that there will be
development effort for the interpreter, test cases, documentation etc.

Of course, you are able to write code with the right nesting, else it
wouldn’t run ;). That doesn’t mean, that it is easy to write or read.

Uglyness was really just a side aspect although I agree I should have
made this more clear. Somehow I must have assumed that the other
points are obvious. :slight_smile:

Is it really that ugly? I want to emphasize that the additions would be
optional. I really think of using it only, when there are three ore more
consecutive ends. But then, it is really helpful (please also see the
example at bottom).

[…] Even such a
small change can cause significant other work to be done.

That is true :confused:

If you want help figuring out how to do this, I’ll be glad to give you
advice, tho you’ll have to write it. Doing something like this the
right way is going to be quite difficult unless you know where to
start, and even after that will be fairly tricky. Unless you’re an
expert on parsing ruby, you need the assistance of someone (like me)
who is.

Thank you for this nice offer. I would gladly take it :slight_smile: [but as I said,
I have much to to do, so it would be possible at the earliest in about a
month].

But we still have different opinions about whether the syntax would
involve punctuation. I think with it, the code is better readable in
cases like this:

def test
while 1
puts (1…9).each_slice(3).map do |slice|
sum = slice.inject do |acc, ele|
acc + ele
end

  if sum > 6
    42
  else
    99
  end~if
end~do.join ','

end~while
end

2010/7/11 Caleb C. [email protected]:

of the rare cases? Even if it would be feasible this sounds like an
awful hack and I’d rather not make parsing more complicated (and thus
slower) as it is today.

The syntax change I proposed requires forbidding a construct which is
currently legal but rarely used and considered to be poor style. What
is wrong with that? In those few cases where someone decided to
separate an ‘if’ from its condition with a newline, the code would
have to be rewritten (inserting a backslash to make the newline soft
is the easiest way). Such constructs should be rewritten anyway, for
purely stylistic reasons.

I mostly agree apart from the missing aspect of efforts. Even such a
small change can cause significant other work to be done.

Now if you want to argue that Jan’s proposal is esthetically
unpleasing, I won’t really disagree. But just leave it at that. I hate
it when people try to throw up a lot of rhetorical chaff when their
real, and only valid, objection amounts to a subjective judgment call.

It’s not only that. I question the balance of effort and benefit.
Since most code around does not use the new syntax, you will have to
support the old syntax as well. As long as it is not mandatory only
people benefit that use it. OTOH, there is additional effort for
backporting new code to projects that only use an old Ruby
interpreter. Given that we do not have this feature today and most
people seem to be able to write code that gets the nesting right I
wonder what the real benefit of this is given that there will be
development effort for the interpreter, test cases, documentation etc.

Uglyness was really just a side aspect although I agree I should have
made this more clear. Somehow I must have assumed that the other
points are obvious. :slight_smile:

Cheers

robert

On Mon, Jul 12, 2010 at 12:59 PM, Jan L. [email protected] wrote:

points are obvious. :slight_smile:

 if sum > 6
   42
 else
   99
 end~if

end~do.join ‘,’
end~while
end

Hi,
I know it’s a bit of a contrived example, and I’m not advocating a
version
of “Ruby Golf” here, but if I saw this method in some code I was
maintaining
I would refactor it to something like:

def test
while 1
puts (1…9).each_slice(3).map do |slice|
sum = slice.inject { |acc, ele| acc + ele }
sum > 6 ? 42 : 99
end.join(’,’)
end
end

…or even better, move the “summing” to another method…

def test
while 1
puts (1…9).each_slice(3).map do |slice|
calculate_sum > 6 ? 42 : 99
end.join(’,’)
end
end

def calculate_sum(items)
items.inject { |acc, ele| acc + ele }
end

I think most cases where the end~if syntax is “necessary” would be
better off
(e.g. more readable) with a healthy dose of refactoring.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs