Hacker Newsnew | past | comments | ask | show | jobs | submit | chucke's commentslogin

lol, the trans-pacific route was pointless. Portugal monopolized the Indian ocean and spice trade for more than 100 years. It established the atlantic triangle trade of Africa (supplying slaves) to Brasil (supplying sugar) to Europe. All of them comercially viable for centuries. Meanwhile, Spain could barely cross the Pacific ocean and make it the viable trade route to the spice islands that it longed for to be.

Many forget that the circumnavigation of Magellan was both a mistake and a failure. The discovered pass to the Pacific, the southernmost point in the planet not counting Antarctica, was considered unnavigable most of the year (the magellan fleet had to wait 6 months at Puerto San Julian before daring to continue the search, surviving its first mutiny attempt), before treading the slow currents of the Pacific, which took down the majority of the fleet to scurvy (while most likely contributing to the madness of Magellan, which made him the delirious zealot which jumped foolishly to his death at the hands of Lapu Lapu). In fact, part of the fleet tried to make it back through the Pacific, only to give up again, come back to the spice islands and be captured by the portuguese, while the remainder barely made it back, commanded by Elcano, one of the mutineers of Puerto San Julian; a route that btw, they feared taking, as it was in direct violation of the Tordesillas treaty and would certainly condemn them to death would they be discovered. 1 ship out of 5 made it back. 18 out of 270 men. By the time they arrived, the new world colonization was still mostly considered a failure, Columbus still an outcast, not even worthy of naming the continent he discovered (this was roughly 18 years before the Aztecs, Incas, and all the gold and silver that got plundered).

Meanwhile, the portuguese routes remained largely uncontested, that is, until a certain young portuguese king died in a battle in the north of Africa leaving no children, thereby opening the door for the two crowns being ruled by the same king, and with it, making Portugal a target for the many enemies Spain had been collecting along the way. And that was the beginning of the end for the portuguese century.

The Manila galeon is certainly an historic milestone, but it connected America with Asia. Payload needed to be carried by land all the way to the Gulf of Mexico before departing to Europe. Barely global, if that's what's implied. It started quite late in the history of the spanish in Americas, some 100 years after the conquest of Mexico, because until then, extracting and transporting all the gold and silver to Europe was considered more profitable, until there was so much silver in circulation in Europe that it devalued it, thereby making Asia a more enticing market for its silver, as it was still considered valuable by then. The route also lasted a bit more than 50 years. Consider that the portuguese route to India was still being navigated way into the end of the 1800s, and only being truly disrupted by the opening of the Suez canal.

I'm not here to downplay the several achievements, or exacerbate the atrocities of the spanish empire. Every empire had them, no less the portuguese (while they did not come up with the idea of slavery, the atlantic triangle is responsible for the biggest intercontinental forced transfer of human beings in history, and the massive economic dependence it created in African kingdoms caused its brutal collapse after the abolition). But not calling it the first global empire of the discovery age, specially taking into consideration that they literally started a century before anyone else, is factually incorrect.


Both are true. Different camps meant that any significant change to the language was scrutinised loudly. If my memory doesn't fail me, the last significant changes from the time Guido was still in charge, and he mostly abandoned the BDFL because of backlash. Since then python has been on a constant "analysis paralysis" state, with only efforts about performance pushing through (no one complains about a faster horse).


> If my memory doesn't fail me, the last significant changes from the time Guido was still in charge, and he mostly abandoned the BDFL because of backlash

I think Guido left the BDFL role in 2018, and we’ve gotten walrus operators, structured matching, and exception groups since then (just off the top of my head). There’s also been significant language/grammar accommodations towards type annotations.

Overall, I’m of the opinion that Python’s language evolution has struck a pretty nice balance — there’s always going to be something new, but I don’t feel like the syntax has stagnated.


The other poster said “The result is that the Python language is pulled in many different directions, and with each release gets increasingly bloated and strays further from its foundations.” Which is directly contradictory to your (more correct) notion that language changes have slowed and only changes with low or no additions of complexity are worked on.


Happy bday ruby!

For the usual doomsdaysayers saying "ruby can't X so I left it for Y", when X is typing, RBS is becoming the accepted standard (now that sorbet supports it),and RBS inline notation next to signature/code too (for peeps complaining about separate files); when X is LSP, ruby-lsp is the standard and already supports "go to definition" (its major hole for a long time), and its plugin architecture allows other other features to reuse the same code AST/index (So that each linter/formatter/type checker doesn't have to parse their own); when X is parallelism, ractors are have actually become performant in a lot of common cases, and it's only missing some GC improvements to be truly non-experimental.

There are new shiny things like ZJIT or Box, but even the core team recommends against using them in production for now. But they'll get better, as its been happening with the things listed above.

No wildly new syntax changes is also a good thing. Should help alternative implementations catch up.


Fairly hardcore rubyist here. Ruby-lsp is excellent. But in no way is RBS becoming standard. Maybe it will, I don’t know. But adoption is very, very low as of today. Rbs-inline is just someone’s pet project and has very little activity (though it does appear that the person who wrote it is trying to implement it directly into Rbs now, which would be great)

Personally I can’t see any comment based typing system gaining real traction.


As long as Matz is firmly against, inline typing should never be a part of Ruby. I started working on a large Rails codebase that adopted Sorbet and it is nothing but an impediment to progress.


I work in a large Sorbet codebase (though it isn't a Rails one) and it's a huge boon IMO. The number of tests we don't need to write because of Sorbet is really nice.

It does occasionally require structuring your code differently, but I find the type-system-encouraged approach often gives a more elegant and harder-to-misuse interface in the end.


You work in a large Ruby codebase that _isn't_ Rails?! Are you hiring??


I was assuming Stripe, but would love to hear of others!


Very curious to hear about the specific cases where types make tests unnecessary.

I spend my working life swapping between Ruby and typescript projects and the typescript project is utter garbage with poor test coverage that needs a day of human QA for every build whereas the Ruby project is well tested such that we know that CI passing means it’s good to be released.


Types don't make testing in general unnecessary, but it removes a class of error handling that runtime type checking handles for you. You can really trust the types when using Sorbet.

(I also work in a 40m+ loc non-rails ruby codebase that is almost entirely typed with Sorbet.)


Haha “tell me you work at Stripe without telling me you work at Stripe”


I think it will need to be a strong 3rd party that basically gives it the Typescript treatment.

Adds type annotations to the core language syntax. The compiler does type checking, strips the annotations, and outputs plain Ruby.


Sorbet is backed by Stripe.

Why is it important to be a separate layer that compiles to plain untyped Ruby?


So that it doesn’t have to go through the Ruby development process. Matz doesn’t want it, and even if he did it would take years just to get people to agree on a syntax, much less actually get it implemented and rolled out.

Same reason Typescript was made and we didn’t add types to JavaScript.


Is Sorbet not what you’re describing?

And RBS is officially part of Ruby…


Neither of them integrate annotations into the language. They’re both bolt-ons and it shows, badly. If either of them were good developer experiences one would have caught on. But they’re both way off the beaten path in terms of what engineers expect in a type system and not in a good way.

Type annotations in the language as syntax. Static type checker with an emphasis on inference. Compiles into Ruby so that it integrates with the entire existing Ruby ecosystem, so unlike Crystal as well.

Those are the general features you need/want and why TS caught on and none of the existing solutions hit the mark.


You might find https://blog.jez.io/history-of-sorbet-syntax/ interesting, written by one of the primary contributors to Sorbet.

Sorbet is a bit different from TypeScript because it has runtime type checking, not just static.


> adopted Sorbet and it is nothing but an impediment to progress

How so?

I never really missed types in Ruby, even if I like them a lot in typescript, but right now I'm doing some "vibe coding" on a personal project and I was thinking about trying Sorbet. I think that it could help Claude Code avoid some mistakes it often makes which make it waste a lot of time fixing.


It’s not a huge impediment but it adds up through: extra lines of sig code I now need to essentially ignore as I read as well as waiting for precommit hooks to check a giant codebase for compliance, plus extra rbi files in git. If engineers followed convention over config and tested types where necessary, no need for inline types. Just use TS if you want types.


Interesting: how is CC in your experience at writing tests and then using them to avoid mistakes?


When writing non-vibe-coded software I use CC a lot to write tests, but I have a skill to tell it not to create redundant tests, which otherwise it tends to do, and I have to check them anyway to ensure that they cover what needs to be covered, and sometimes to trim them down.

When vibe coding, what I noticed is that CC tends to make mistakes which it does catch with tests and fix on its own, but my hope is that using Sorbet this will happen much less, and thus development will go faster with less (slow) test cycles.


Very interested to read the blog post about the results.


DHH also doesn’t like typing in Ruby at all, and Rails is designed around what he likes.


Maybe I wasn't clear, but until now there were 2 types of type notations being debated, RBS and sorbet/RBI. Sorbet adopting RBS means that's the lowest common denominator. Typing is definitely not a standard, not yet. rbs-inline is definitely not a pet project, it's the RBS creator response to the main complaint about RbS , its the reason sorbet finally adopted it, and will be part of mainline rbs gem.


It’s just inferior to Python, nobody is making a more complex argument than that. Why ever use Ruby when there’s a virtually identical system that’s faster with a bigger community.


Because Ruby is just a better thought out language than Python is. It had a sane package management story 15 years before Python. It doesn't rely on weird hacks like exception throwing for iterator control flow. It doesn't have nearly as many warts and footguns on basic operations (for example, in Python csv.writer(file).writerows(rows) is broken unless you remembered to set the newline mode on the file; in Ruby file.write(rows.to_csv) just works). Thanks to a sane VM design it's mainline JIT can actually run code faster than interpreted code (something that CPython's JIT can't do [1])

Many Pythonistas are woefully ignorant of what's going on outside their siloed community.

[1] https://fidget-spinner.github.io/posts/jit-reflections.html


Everything being mutable by default, including strings, is about as big a foot gun as you can find in a high level language.


Having immutable objects by default isn’t incredibly commonplace outside of functional languages. It certainly isn’t unique to Ruby and seems out of place in a discussion comparing Ruby to Python. Fortunately, you can defensively freeze any objects you’re passing around to avoid the most common issues with mutable objects.

Immutable strings is a more popular programming language feature and Ruby has a mechanism for opting into that. It’s so commonplace that the complaint usually isn’t that a string can be modified, but rather that every source file includes a magic comment to prevent that. Besides data safety, the VM can optimize frozen strings, so popular linters will flip that setting on for you. String mutability isn’t a practical issue for modern codebases. And, as language design goes, it’s kinda nice not needing to use a parallel set of classes for mutable and immutable string data IMHO.

With that said, the magic comment is a wart and folks are looking at making immutable strings the default. But, there’s a strong desire to avoid breaking the world. The Ruby Core team is keen to keep the lessons learned from the Python 2 -> 3 migration in mind.


> With that said, the magic comment is a wart

Not only a wart but a massive foot gun, not shared by any other language, as I said. It is incredibly common to create hash tables using strings as keys, and Ruby makes this dangerous by default.

> Having immutable objects by default isn’t incredibly commonplace outside of functional languages

They make it easy to create immutable objects. Python has tuples and immutable data classes. Strings are immutable.

> The Ruby Core team is keen to keep the lessons learned from the Python 2 -> 3 migration in mind.

In the meantime, this ridiculous foot gun that no other language shares exists. That is a fact, and the fix being hard does not make it any less of a fact.


In what ways is it inferior? Neither Ruby or Python are 'fast', so if that is one of your qualifiers you've already made a suboptimal choice.

As for a bigger community, what does that serve? The large python community adds misdirection and more voices to a language that lacks some basic features still. Async/sync code models are still being finalized whereas Ruby has been stable in this regard for 10+ years. Same with tooling - the Ruby side is more consistent and stable: Sidekiq for background jobs (Celery is barely coming to maturity), Bundler for dependencies (pip? poetry? uv?). Mature auth + other frameworks like Devise.

Having worked in both languages professionally, I strongly disagree with your take.


Ruby is a lot less awful than Python in my opinion. That is of course a very subjective opinion. The only reason I write more Python than Ruby is that ruby lacks the libraries I need.

Somewhere along the line Python got all the momentum, and ruby got none and now python is better if you just want to get shit done.

But man. I wish it was the other way around. I have one code snippet that summarises what I dislike about python:

    if input() == "dynamic scope?":
        defined = "happyhappy"
    print(defined)
    
Seeing that I understand why I see yuck in just about every corner of python.

Edit: in ruby it also works, but the variable is at least always defined.


I’m sure I’ll get downvoted for it, but strict technical merits aside, Python to me seems built by engineers who lacked any sense of taste. Ruby is beautiful.


> in ruby it also works, but the variable is at least always defined.

How is this even a pro? I agree that Python scoping rules are frustrating, but tbh not sure if I would prefer Ruby's behavior in this case


Well. If python is a dynamically scoped language, what they do is correct. If they are lexically scoped (which python is described as) the variable defined in the if should never have different visibility in the same scope.

In a lexically scoped language you don't define variables conditionally. What ruby does is also icky, but obviously the developers of both python and ruby wanted to save the developer an extra declaration. The ruby version is at least more correct from a lexical standpoint (it is set to nil if left "nondefined").


Blanket statements like this are unhelpfully tribal. Ruby has its uses, and underpins one of the most successful (and cloned) MVC frameworks of all time. But yeah, Python received the attention of data scientists early on and now it's a lingua franca of sorts in that domain. Since AI is so hot right now that makes Python seem superior, but really that's just contingency.

If you're going to make claims, support them.


> that’s faster

In every test I've done, Ruby has been faster than Python. In my experience that's been the case since Ruby 1.9, with the move to YARV.


I don't think anyone says: "I switched from Python to Ruby" (of vice versa) for performance.


True. Choosing between the two languages usually comes down to their library ecosystems - or more bluntly, to Rails on one hand vs NumPy on the other.

Nonetheless, it's still common for people to talk about the relative performance of the two languages, and to claim that Ruby is slower than Python. As someone who's actually tested this, it hasn't been true for 15 years.


> Why ever use Ruby when there’s a virtually identical system [...] with a bigger community.

There was a time in the history of Python when people who chose Python did so primarily because they found it beautiful or pleasant to work with. These are reasonable factors in choosing a language, and they continue to be popular reasons for choosing relatively unpopular languages today.

A related essay has made the rounds on HN before. It might be worth revisiting if this question is on your mind: https://www.johndcook.com/blog/2011/10/26/python-is-a-volunt...


Why? Because Python is generally slower, uses significant whitespace in its syntax, and lacks the metaprogramming features of Ruby.


Python is great and I love writing glue in it, but Ruby is just a better designed language and ecosystem overall.


A lot of times 2-3 lines of Ruby needs 5-8 lines in Python.


Ruby/rails has always felt fragile to me. Like you have to write the same tests over and over to make up for the looseness of it, not to mention the culture of breaking changes adds insult to injury. Just seems like a mess and the nice syntax (subjectively) isn't nearly enough to win when better options exist.


Static typing has come, there's RBS, which has (finally) coalesced (after adding support for inlining in code) as the blessed type notation, supported by both steep and sorbet. Considering that big companies have adopted it, I'd say that the community agrees and has done something about it. But as you can imagine, many ruby apps have been stuck in legacy for years.

About performance, not sure how you think static typing could solve it, but considering the significant investment recently in JITs, in particular YJIT and ZJIT, again, the big apps seem to agree with you and have done something about it?

Even if you ditch CRuby for the JVM, you can still use JRuby, and still leverage the language while not being pulled down by the runtime.

It's not like you're without options.


Lmk when the app launches, will beta test if for free.


What is the real problem being solved here? For all the issues that bundler still has, rv doesn't seem to address most of them. Bundler has been fast enough for a while now, how fast does this need to be? And do we now have to know rust to contribute?

If indirect is salty that the rubygems/bundler didn't turn out yet to be what he wanted, I wonder whether a simpler and faster alternative to bundler written in RUBY wouldn't be the answer, with incremental merges into bundler. Gel was mostly there, even if most never knew about it, but at least it got the bundler ppl to merge the pub grub resolver.


The listen gem works on windows: https://github.com/guard/listen?tab=readme-ov-file#listen-ad... . Not sure whether guard builds on top of it.


Bear in mind that: the author is part of the ruby core team; json is a standard lib gem; the repo from the json gem was in the original author namespace; the repo had no activity for more than a year, despite several quality MRs.

It took some time to track and get the original author to migrate it to the ruby team namespace.

While I'm glad they to all this trouble, there's only a few who could pull this off. Everyone else would flock to or build a narrative.


I wonder whether the reason for this is a lack of available certified oauth libraries on top of which to build a provider at the time it was built, which led most of these examples to roll their own, with the obvious flaws. There isn't yet such a certification for oauth, although the oidc federation certifies and lists a bunch of them: https://openid.net/developers/certified-openid-connect-imple... (I maintain one of them). Which is the next best thing.


> DBOS has a special @DBOS.Transaction decorator. This runs the entire step inside a Postgres transaction. This guarantees exactly-once execution for databases transactional steps.

I stopped here. I know, authors really want to chase the exactly-once dragon, but this won't scale. If the step takes a long time, it'll keep the transaction open with it for that time. The master replica has to bookkeeping that. That state has to be replicated. That will also affect MVVC further on. As your scale grows, you'll see disk usage growing and eventually swapping, replica lags, AND vacuum halting for surges. I hope your uncalled engineers have a steady supply of coffee.


Yes, that's why the @DBOS.Transaction is just for database operations, which (hopefully!) you've already optimized to not take unreasonable time. These are guaranteed to execute exactly-once. For other, potentially longer-running operations, use @DBOS.step, which is at-least-once. Documentation:

Transactions: https://docs.dbos.dev/python/tutorials/transaction-tutorial

Steps: https://docs.dbos.dev/python/tutorials/step-tutorial


OK, I see I skipped that. Nevertheless, I would expect users to read "exactly once" and put an http call in the step. It's the type of knife people their hands with.


One of the features on our list is to actually warn people when they make external calls inside of a step for this exact reason. You're right, the developer does need to understand idempotency to be successful, but we do everything we can to make sure they are successful without that knowledge.


I, too, found this "exactly-once" language really unclear and a turn-off. What does it actually say that is meaningful and helpful? I can run a transaction in any language and I get, surprise, transactional semantics.


Exactly, I'm surprised that DBOS was founded by the Postgres creator


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: