Hacker News new | ask | show | jobs
by wewewedxfgdf 299 days ago
It's the never ending "end"s that bother me about Ruby.

    class Mess
    def chaos(x)
        if x > 0
        [1,2,3].each do |i|
            case i
            when 1
            if i.odd?
                puts "odd"
            else
                puts "even"
            end
            when 2
            begin
                puts "trying"
            rescue
                puts "failed"
            end
            else
            puts "other"
            end
        end
        else
        puts "negative"
        end
    end
    end
Clear away all those ends and the program logic pops out. Much fresher!

    class Mess:
        def chaos(self, x):
            if x > 0:
                for i in [1, 2, 3]:
                    match i:
                        case 1:
                            if i % 2 == 1:
                                print("odd")
                            else:
                                print("even")
                        case 2:
                            try:
                                print("trying")
                            except:
                                print("failed")
                        case _:
                            print("other")
            else:
                print("negative")
6 comments

The indent in your Ruby code is a bit weird. It should be like this

    class Mess
      def chaos(x)
        if x > 0
          [1, 2, 3].each do |i|
            case i
            when 1
              if i.odd?
                puts "odd"
              else
                puts "even"
              end
            when 2
              begin
                puts "trying"
              rescue
                puts "failed"
              end
            else
              puts "other"
            end
          end
        else
          puts "negative"
        end
      end
    end

I would have done it this way instead

    class Mess
      def chaos(x)
        if x > 0
          [1, 2, 3].each do |i|
            case i
            when 1
              puts i.odd? ? "odd" : "even"
            when 2
              puts "trying"
            else
              puts "other"
            end
          end
        else
          puts "negative"
        end
      end
    end
Or if you allow me to create a separate private method

    class Mess
      def chaos(x)
        return puts "negative" unless x > 0
    
        [1, 2, 3].each { |i| handle_item(i) }
      end

      private
      def handle_item(i)
        case i
        when 1 then puts(i.odd? ? "odd" : "even")
        when 2 then puts "trying"
        else        puts "other"
        end
      end
    end
I'll leave aside the unnecessary test for parity as contrived for the example.

This is a question of style; it's possible to write ruby the way you have but with experience you definitely wouldn't.

e.g.

Why wrap the iterator in an if..else..end block? You could replace that with a one line guard statement at the top of the method. No end required.

Why use begin..rescue..end in the middle of your example? Just replace that with a single rescue at the end of the method. Again, no end statement required.

This is like nesting 20 if..else blocks in python and then complaining you don't have a monitor big enough to view it without scrolling. You just wouldn't do it that way.

My hope is that with the new ruby parser rubocop will be more agressive about automatically refactoring examples like this away.

That Python code looks like it was punched in the belly and is about to fall down on itself like a Jenga tower. Additionally, the last `else` is hard to track visually and if you make the slightest error in whitespace (which are invisible characters!), everything breaks.

To each their own. It’s because we all have different preferences that there are so many choices.

I'd love Python if it weren't for whitespace. I wanna cut/paste code into a REPL, and Python makes that difficult.
I find that the IPython REPL has downright amazing multiline support. I've always been envious of it when using GHCI. But even the standard Python REPL supports multiline paste just fine. So what exactly are you talking about? Rolling your own?
You can't copy a method from a class and then paste it in the REPL, it will complain about indentation.

Workarounds:

1) copy whole class

2) remove indentation before copying

That's only a problem in the base python interpreter. IPython has handled this well for over 20 years.
Begin/end should be optional. Some things would just be so much easier to follow, map/lambda stuff cleaner.
But the previous commenter just improved the Ruby code by adding whitespace!
It's not Ruby, it's your code... :D

class Mess

  OUTPUTS = {
    1 => ->(i) { i.odd? ? "odd" : "even" },
    2 => ->(_) { "trying" },
    3 => ->(_) { "other" }
  }.freeze

  def chaos(x)
    return puts "negative" unless x.positive?
    
    [1, 2, 3].each do |i|
      puts OUTPUTS[i]&.call(i) || "other"
    end
  end
end
And I have no idea why HN messes up my class statement... it looks good in the text field :D
Did you start it with two spaces? That's how HN does code blocks. Two spaces added before each line. The other lines look fine because they were already indented, add two spaces before all of them and it'll look fine.
I mean, that's a horrific piece of Ruby that doesn't do much, and you've not indented it properly.

Of course you can get all this down to a single line with ; demarcation.

And your `.each` could use `{ ... }` syntax, just like C or Java or... you know, everything else.

But sure, whitespace is better, or whatever it is you prefer.