128 Followers
172 Following
316 Posts
I'm a Rubyist, I've been writing code since 1981, since I was 8 years old. I'm a father, husband, sailor, and overall nice guy. I'm HoH/Deaf, I speak English, but prefer ASL. (he/him)
github.comhttps://github.com/jimnanney
Code generation tools fix the problem of software development being slow and expensive in much the same way that faster cars fix traffic congestion.

I love how enumeration can be customized in Ruby ❤️

Did you know you can write your own Enumerator helpers, like `.with_index` and `.with_object`?

I searched the web, and informations on this is relatively scarce.

So here's a few paragraphs to show how useful it can be! ➡️ https://kemenaran.winosx.com/posts/ruby-crafting-enumerator-helpers

#programming #dev #ruby

Crafting Enumerator helpers in Ruby

Among all the powerful abilities of Ruby Enumerators, one of their most useful usage is to customize what gets enumerated. For instance, by default #each will yield the elements of the enumeration, one by one: array = ["apple", "banana", "grape"] array.each do |value| puts "${value}" end # "apple" # "banana" # "grape" In some cases, however, we may also need the index of the element being enumerated. For this, we can use Enumerator#with_index. It turns an existing enumerator into one that also yields the index: array.each.with_index do |value, index| puts "${index}: ${value}" end # "1: apple" # "2: banana" # "3: grape" The neat thing: this works for any enumerator! For instance, if you’re not enumerating using #each, but rather using #map or #filter, the usage is the same: array.map.with_index do |value, index| "${index}. ${value.uppercase}" end # ["1. APPLE", "2. BANANA", "3. GRAPE"] How to craft your own enumerator helpers Recently, I wanted to enumerate the pixels of an image. The pixels are represented a single-dimensional array of integers: image.pixels # [998367, 251482, 4426993, 777738, ... ] However, in my case, I want to perform different operations depending on the pixel coordinates. Of course, we can compute the coordinates in the loop itself: pixels.map.with_index do |pixel, i| x = i % image.width y = i / image.width pixel * ((x + y) / 100.0) # brighten from top-left to bottom-right end But there has to be a better way. What if we could substitute the enumerator’s .with_index by something like .with_coordinates? First, I needed a quick refresher on how to write a method that enumerates on values. AppSignal’s article on Enumerators is quite a good read there. So, our method just need to yield the values one-by-one, and that’s it? Let’s try this. We’re going to re-open the Enumerator class, and add a #with_coordinates(width, &block) method: class Enumerator def with_coordinates(width, &block) each.with_index do |value, i| x = i % width y = i / width yield value, x, y end end end When called, Enumerator#with_coordinates will invoke its block once for each of the enumerator values - passing the coordinates along. Let’s see how it is used: pixels.map.with_coordinates(image.width) do |pixel, x, y| pixel * ((x + y) / 100.0) # brighten from top-left to bottom-right end The coordinates computation are pushed away from the block, the code is nicer… Good work. Plus #with_coordinates works not only for #each, but for any enumerator – juste like #with_index! Method chaining on enumerators There’s only one caveat though: in Ruby, enumerators support method chaining. That is, instead of passing a block to the enumerator, we can instead call methods on it. Like this: pixels .each .with_index .with_object("filename.png") do |pixel, i, path| puts "Pixel at #{path}:#{i} => #{pixel}" if i = 5 end # "Pixel at filename.png:5 => 1962883" But if we try this with our current implementation of Enumerator#with_coordinates, we get: pixels .each .with_coordinates(width) .with_object("filename.png") do |pixel, x, y, path| puts "Pixel at #{path}:#{x}:#{y} => #{pixel}" if i = 5 end # in `block in with_coordinates': no block given (yield) # (LocalJumpError) Makes sense: our helper yields to a block, but Ruby complains that none was provided. To fix this, we’ll need to return an Enumerator instance when our #with_coordinates function is called without a block. Let’s modify our implementation of Enumerator#with_coordinates: class Enumerator def with_coordinates(width, &block) + if block_given? each.with_index do |value, i| x = i % width y = i / width yield value, x, y end + else + Enumerator.new do |y| + with_coordinates(width, &y) + end end end end And there we have it: using the block-less form will return a new Enumerator. pixels.each.with_coordinates(width) # <#Enumerator: ...> Which means we can properly chain #with_coordinates with further methods now: pixels .each .with_coordinates(width) .with_object("filename.png") do |pixel, x, y, path| puts "Pixel at #{path}:#{x}:#{y} => #{pixel}" if i = 5 end # "Pixel at filename.png:1:1 => 1962883" And that concludes our short side-quest on implementing Enumerator helpers in Ruby. It feels very expressive; and I like how we can make our custom helpers as powerful as the native ones. Happy enumerating!

Kzone

Would really love to find a Staff-like remote full time role in the US working, ideally, in #Ruby but also open to

I've experience in many different programming languages/stacks from decades in the field: Ruby and Java (over a decade each), C, Erlang, Golang, Python, PERL, JavaScript, and several others.

I've experience both as a manager of up to 15 people (5 years) and an IC (decades).

Server-side of distributed systems is my jam. REST API design and enhancement, job processing, data warehousing, event sourcing, authorization systems, etc. I've experience with Kafka, RabbitMQ, Postgres, Redis.

I've experience with machine learning from before it was hot, ETLing data from various sources to sanitize it enough to build a model against it.

Test Driven Development is how I design and write my best code. It's more than "writing the tests first".

I believe in operating the software that I write/maintain. Having skin in the game helps ensure that the software runs well. I'm comfortable with healthy oncall expectations.

Also very open to learning more. I've been eager for an excuse to get my hands dirty with Rust and Elixir.

Boosts appreciated.

#seekingwork #FediHire

If you are patient enough, you can build your very own Boeing airplane out of parts that fall from the sky.

🤔I got asked about this yesterday from a neighbor, a teacher in our local school district.

Teacher: "Isn't AI 4 to 5 times faster/better at coding than the best developers?"

Me: "Isn't AI 4 to 5 times faster/better at teaching than the best teachers?”

(shocked/disgusted look on her face)

🤷 And that's one of the problems of AI. It seems better than you at something you know nothing about because you don't quite know well enough to call it out on its bullshit. https://toot.cafe/@baldur/112031199817039932

Baldur Bjarnason (@[email protected])

JFC, people in tech are really out there saying that language models will be better at therapy, financial advice, and career advice than trained people. WTF is wrong with you people? Do you really have no clue about what other people’s jobs actually involve? Language models can’t even do maths how are they supposed to get good at financial advice? And therapy? Just… 😑 What’s wrong with people in tech?

Toot Café
Math should be done with American numbers
A good friend and coworker @gd just had his book go to print. https://hands-on-tdd.com/ I've worked with him for 5 years, and I can tell you, it's a good book on TDD coming from true hands on experience! Buy your copy and leave him a review today!
Hands-on Test-Driven Development - Using Ruby, Ruby on Rails, and RSpec

A book for learning hands-on test-driven development using Ruby, Ruby on Rails, and RSpec.

Validation is the opposite of #UserResearch.

Research asks: how are we not serving existing needs? How do problems manifest themselves and what can we do about it?

The default is "there is a problem somewhere out there because we know we are not perfect."

But validation is only asking "is the idea we came up with viable" and that introduces confirmation bias.

The default is framed as "we are right" so we stop as soon as we find someone that our solution works for.

You see the problem.

#ux

nothing is more permanent than a temporary solution https://github.com/Apple-FOSS-Mirror/Libc/blame/master/sys/__libc_init.c#L69
Blaming Libc/sys/__libc_init.c at master · Apple-FOSS-Mirror/Libc

Contribute to Apple-FOSS-Mirror/Libc development by creating an account on GitHub.

GitHub
See the History of a Method with git log -L: http://calebhearth.com/a/git-method-history
See the History of a Method with git log -L

Git can “trace the evolution” of a specific method, showing you logs of how it has changed over time.

Hearthside