Live data from Hacker News

Ruby delights built into the language

technology.doximity.com

31–40 of 89 posts

Re: Ruby delights built into the language

#31
post #16

This article is kind of niche... My favourite Ruby delights are among others, methods provided by the Enumerable mixin https://rubyapi.org/3.1/o/enumerable . There's a pile of functionality there that helps with tedious tasks. E.g. here's a solution to this year's AOC challenge #6 using Enumerable's each_cons method: File.read('input6.txt').chars.each_cons(4).find_index { _1.uniq == _1 } + 4

I struggle with code like this (also, complicated piped shell statements). How do you debug/reason about this? I know this specific example may be an exercise, but still.

> How do you debug/reason about this?

Debug? You don’t. You have to break your sexy chained-functional-style 1-liner into a “boring” multi-line loop to actually set meaningful breakpoints and work through any problems that may arise. Which is why I dislike this style of code — once something goes wrong, it’s WAY more cumbersome to debug and almost always makes you “unroll” it into its boring, “classic” form. And, of course, once you do that, you’re now debugging something DIFFERENT than what’s shipping in production! And you have to be extra careful to ensure that all of the logic has been kept the same, lest you ship a patch that doesn’t actually fix the bug! This is my prototypical “what programming is NEVER about” example: programming is never about how pretty the code is. Programming is about shipping features, and then being able to diagnose and fix problems with what you shipped.

Re: Ruby delights built into the language

#33
post #16

Earlier quoted context omitted.

I struggle with code like this (also, complicated piped shell statements). How do you debug/reason about this? I know this specific example may be an exercise, but still.

> How do you debug/reason about this? Debug? You don’t. You have to break your sexy chained-functional-style 1-liner into a “boring” multi-line loop to actually set meaningful breakpoints and work through any problems that may arise. Which is why I dislike this style of code — once something goes wrong, it’s WAY more cumbersome to debug and almost always makes you “unroll” it into its boring, “classic” form. And, of…

That is both plainly incorrect (you can drop a breakpoint without breaking the chain, see comment below), and missing the point -- I mean, I appreciate the lecture on what programming is all about, but in this case the programming is all about having fun, and writing a solution as fast as possible ¯\_(ツ)_/¯.

Re: Ruby delights built into the language

#34

Earlier quoted context omitted.

> How do you debug/reason about this? Debug? You don’t. You have to break your sexy chained-functional-style 1-liner into a “boring” multi-line loop to actually set meaningful breakpoints and work through any problems that may arise. Which is why I dislike this style of code — once something goes wrong, it’s WAY more cumbersome to debug and almost always makes you “unroll” it into its boring, “classic” form. And, of…

That is both plainly incorrect (you can drop a breakpoint without breaking the chain, see comment below), and missing the point -- I mean, I appreciate the lecture on what programming is all about, but in this case the programming is all about having fun, and writing a solution as fast as possible ¯\_(ツ)_/¯.

So you have to add code to debug it with #tap? I don’t care if the chain is unbroken: you have to CHANGE THE CODE YOU SHIPPED in order to properly debug it. That’s idiotic. And before you say “oh, this is just an exercise”, I can tell you from personal experience that I encounter this endlessly in prod code with both Python and Kotlin chained functional style garbage. It is often not debuggable without break-up and unrolling.

Re: Ruby delights built into the language

#35
post #16

This article is kind of niche... My favourite Ruby delights are among others, methods provided by the Enumerable mixin https://rubyapi.org/3.1/o/enumerable . There's a pile of functionality there that helps with tedious tasks. E.g. here's a solution to this year's AOC challenge #6 using Enumerable's each_cons method: File.read('input6.txt').chars.each_cons(4).find_index { _1.uniq == _1 } + 4

I struggle with code like this (also, complicated piped shell statements). How do you debug/reason about this? I know this specific example may be an exercise, but still.

Ruby is a surprisingly simple language. Metaprogramming in ruby is a pretty good book that makes it clear what is happening under the hood.

The yield is probably the most complicated part of it, but it is extremely useful for hiding complexity. Once you understand yield, there is very little magic to what ruby is doing.

I prefer python to ruby, but the concept is the same:

https://realpython.com/introduction-to-python-generators/

As for understanding the command line/reasoning about it, they are usually generated iteratively.

  Look at a file to see what you have to work with:
    $ cat $file | head -n 5
  Decide commas aren't useful and remove them
    $ cat $file | sed 's/,//g' | head -n 5
  Decide you want a tab between every 4 characters on any given line
    $ cat $file | sed 's/,//g' | sed 's/\(....\)/\1\t/g' | head -n 5
Each step of the way you see the output, and every additional pipe modifies the last seen output.

Everything else is just being aware of what tools you can use (sed/awk/grep/xargs/etc) and the limits of the data you work with.

GP may have done something like popping the ruby repl, irb, and then:

  File.read('input6.txt').chars
  File.read('input6.txt').chars.each_cons(4).to_a
  File.read('input6.txt').chars.each_cons(4).find_index { _1.uniq == _1 } + 4

Re: Ruby delights built into the language

#36
post #24

This article is kind of niche... My favourite Ruby delights are among others, methods provided by the Enumerable mixin https://rubyapi.org/3.1/o/enumerable . There's a pile of functionality there that helps with tedious tasks. E.g. here's a solution to this year's AOC challenge #6 using Enumerable's each_cons method: File.read('input6.txt').chars.each_cons(4).find_index { _1.uniq == _1 } + 4

Hmm that's a good show of Ruby's great built-ins for Enumerable, but can't any language with a findIndex and a Set achieve the same thing? I.e. in JS: myString.split('').findIndex((c, i, arr) => new Set(arr.slice(i-4, i)).size == 4)

Personally I find the Ruby easier to read. Just follow the functions left to right, and the method names are more literate (chars() vs split('') for instance). I’m also not sure at first what slicing on an array with a negative start index will do, whereas I’m sure each_cons does just what it purports to do.

Re: Ruby delights built into the language

#37
post #28

Earlier quoted context omitted.

I love method_missing - one simple method unlocks so much power and eliminates so much boiler plate.

… and ruins the life of future maintainers, there’s a reason few languages tried to borrow features from ruby’s metaprogramming (saying this as a rubyist)

Any language feature can be misused. But without it things that are easy and useful become hard.

Re: Ruby delights built into the language

#38
post #24

Earlier quoted context omitted.

Hmm that's a good show of Ruby's great built-ins for Enumerable, but can't any language with a findIndex and a Set achieve the same thing? I.e. in JS: myString.split('').findIndex((c, i, arr) => new Set(arr.slice(i-4, i)).size == 4)

Personally I find the Ruby easier to read. Just follow the functions left to right, and the method names are more literate (chars() vs split('') for instance). I’m also not sure at first what slicing on an array with a negative start index will do, whereas I’m sure each_cons does just what it purports to do.

Fair enough. In js slicing with a negative index would grab from the end of the array, but if the end index is positive it'll return an empty string so it's safe in this case

I think the tradeoff is how much of the API you need to memorize. In JS if you know .filter, .map, and .reduce you're good for 95% of use-cases (technically .reduce can be used to implement every other method, but it can get messy). I also work with Ruby at my job and I constantly find myself wondering if this is the best tool for the situation

This was my first job using Ruby so it's definitely become less of a problem over time and I think if it's your MAIN language then having a fat API like that is fine. But I do think there's a trade-off and it can introduce more spaces for bad practices

Re: Ruby delights built into the language

#39

I appreciate the Ruby love in this post, but it's worth pointing out that the author is clearly new to the language. I say that because he writes Ruby as if he's writing some other language, and not idiomatic Ruby. This: dirp = Dir.open(".") for f in dirp case f when /\.rb\z/ print f, "\n" else # do not print end end dirp.close Could be made much more Ruby-native (and simpler!) as: Dir.open('.').each do |f| puts f if…

You couldn't be more wrong, and a simple Google search of the author was all you had to do lol. It's pretty clear here (given his background) that the author is writing in a style to make the code examples more accessible to a wider audience.

Re: Ruby delights built into the language

#40

Earlier quoted context omitted.

That is both plainly incorrect (you can drop a breakpoint without breaking the chain, see comment below), and missing the point -- I mean, I appreciate the lecture on what programming is all about, but in this case the programming is all about having fun, and writing a solution as fast as possible ¯\_(ツ)_/¯.

So you have to add code to debug it with #tap? I don’t care if the chain is unbroken: you have to CHANGE THE CODE YOU SHIPPED in order to properly debug it. That’s idiotic. And before you say “oh, this is just an exercise”, I can tell you from personal experience that I encounter this endlessly in prod code with both Python and Kotlin chained functional style garbage. It is often not debuggable without break-up and u…

> you have to CHANGE THE CODE YOU SHIPPED in order to properly debug it

If I'm at the point where I need to debug a production process with breakpoints, I'd rather just find a new job than worry about my coworker's coding style.

Post reply on HN