A no-go fantasy: writing Go in Ruby with Ruby Next
evilmartians.com
evilmartians.com
As a non Ruby programmer I still appreciate its culture whose community best seems to explore code as art. One of Ruby's contributors @mame (also a talented #1 IOCCC winner) does this a lot who's famous for quine-relay [1] but has lots of other interesting art code projects in their repos.
This kind of stuff is the bread and butter of Racket. For example Racket comes bundled with an implementation of Algol 60 that lets you write Algol in your Racket programs. https://docs.racket-lang.org/algol60/
There's two implementations of Javascript https://docs.racket-lang.org/ecmascript/index.html and https://docs.racket-lang.org/javascript/intro.html, an implementation of Forth https://docs.racket-lang.org/forth/index.html and a lot more.
https://github.com/racket/algol60/blob/master/examples/nquee...
I used to try to write things in the most popular language for those things, like writing Prometheus exporters in Go. But I eventually realised I just didn't care that much, and now I write them in Ruby, and everything is sunshine and happiness again.
At the end we did a demo where we clustered all of our pis and we could send messages to each other's lcd screens.
Edit: protip go to the GitHub of the training person: https://github.com/jjcarstens/nervesconf2021_training
I guess any languages that have some kind of macros, like C, scala or rust.
Rewriting from Ruby to Go, some benchmarks for calculating long streaks showed going from ~5 sec to ~0.04 sec [2].
Conjure's habits use the iCalendar Recurrence Rule format (RRULE [3]) for their frequency, along with one or two other considerations (like Habit Completion Types and streak effects), which makes evaluating streaks more expensive (as you have to work backwards through habit completions one by one based on the next occurrence).
Data is still fetched from Postgres in Rails and passed to the compiled Go library and Ruby/Rails handles the results (persisting, notifying over web sockets, etc)[4]. I modified Conjure's Heroku buildpack to install Go and build on deploy.
No doubt there is further optimizations that can be made, but this approach has allowed me to sprinkle Go into a Rails app and progressively optimize certain things when needed.
[1] https://conjure.so/ [2] https://twitter.com/Whelton/status/1370482793558458370 [3] https://icalendar.org/iCalendar-RFC-5545/3-8-5-3-recurrence-... [4] https://jondot.medium.com/ruby-and-go-sitting-in-a-tree-38c1...
This is why sometimes it's worth looking for obscure methods in the core or standard library and use them instead of writing Ruby code, especially when iterating on Enumerables. Basically it's rewriting Ruby in C.
Entry level example: minmax_by [1] which does the obvious thing but it's not obvious that every Ruby developer knows about it (disclaimer: I went to the docs and looked for something with a fun name.)
[1] https://ruby-doc.org/core-3.0.1/Enumerable.html#method-i-min...
It is?
It is… burlesque!
But full Ruby dispatching is a little crazy (right up there with CLOS or Moose or Groovy) and I can't blame them for not wanting to implement that from scratch.
I think CRuby’s limit on the total number of Fibrrs would be lower than the number of go routines that can normally be supported, but TruffleRuby using Project Loom’s virtual threads could support vast numbers of Fibers when I prototyped it several years ago.
For instance, if there is an order-of-operations disagreement between the two languages, the only solution that works fully is to do a full parse anyhow, because no amount of regex can ever cover all the bases in that case. And that's just an easily-understandable example of irreconcilable grammar differences, they can pop up anywhere (disagreements about reserved words, disagreements about what constitutes legal identifiers, etc.), and when they do you end up backed into doing a full parse of the original language anyhow.
You can then either interpret or compile the resulting AST. That's actually not too hard; what's hard is implementing the more advanced stuff like reflection in Go or dealing with the unsafe package. (If you don't need that, then great! Problem solved.) With the AST in hand you no longer need to worry about those differences.
I don't know ruby well enough to say, but I know Python, a very close neighbor, has everything you need to be able to write a Python module that would allow you to directly import Go modules. With effort it could even compile the Go into Python bytecode directly.
However I had no choice but to use python because it was variously used in practice. I felt it was difficult to persuade my colleagues to use ruby instead of python. Colleagues were not familiar with ruby and there wasn't any ruby project in my company. So I chose python and kept using it for several years. After the decision I didn't try learning ruby because I though they have many characteristic in common and I thought it was meaningless to know both of them, besides I had no time to study it.
It has been several years since I gave up learning ruby, but I still have unresolved feeling about it. Whenever I read articles that highlight the power of ruby, I want to know about it. Haha.. But still there are high prioritized tasks to do. Learning ruby is still remained in the todo list.
Jokes aside, this is insanely cool.
Also the good part of Go are the goroutines, the channels, the types, the safety...
The article was fun but they will find the limit as soon as they will try to support the important parts of Go.
Trying to go further will just demonstrate the opposite of their point.
[0] though there is a rich history of "lol jk" projects ending up in production, I'll admit
Surely you jest. Go's type system is the worst thing about it by a country mile.
And if you think I‘m sarcastic, we might have a different belief system underneath: For me the irreplaceability of an engineer is not measured in the creation of complexity and the mastering of technical acuity in a language that‘s hard to grasp — but much more about the value and delight any piece of code brings to its users through simplicity.
A language that is fast, easy and simple by default and doesn‘t get in the way of people trying to build something for the first time is a feature, not a bug.
My main gripe with Go is it doesn't seem geared toward figuring out new things, or letting people hack and experiment during development.
I came to Go from Ruby (and Python too, but I mostly used it before 2.7) and soon enough all my hacks and "let's try it this way" projects were in Go.
>It doesn't yell at you for having unused variables which is nice for actually developing the software.
No it is not. That was my first impression too but after a few weeks you understand that this was just a bad habit. Not a practice.
My main job for the past 5-6 years is system integration and I had a chance to compare Ruby and Go in this field.
And this is definitely where I'd prefer Go to most other languages. You don't need clever code most of the time, you need really clear and safe code that will run for a decade after deployment.
The question which language makes it easier to write such code (assuming it still should be readable and maintainable, even by the new employees, even if they are not familiar with all the tech behind it)
But I agree that Go doesn't offer a lot for people who like to fiddle around endlessly with the language features - OTOH this allows you to concentrate on the thing you should be fiddling with, which is the actual implementation.
And what about making it easy for them not to make mistakes?