Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Back when autocompletion and stuff were only available in Visual Studio/Xcode/Other bug IDEs, I was forced to use Ruby and fell in love with it. It didn't matter what I used as my editor was Sublime. But when VSCode came and language features became democratized, I never touched a type-less language again. Why should someone opt for a language with absolutely no features where one can have autocompletion, typechecking, deep data type exploration, jumping to definitions and implementations? I really think it's a bad choice of Ruby not to care for types. And well we now have Crystal which again makes me question why Ruby? And it’s a shame no language is as beautiful as Ruby, not in features choices, design elegance, balance, beauty of the syntax, joy of programming mindset, not even in the name and logo. I wished Matz rethinked this part.


> it’s a shame no language is as beautiful as Ruby [...] I really think it's a bad choice of Ruby not to care for types

Do you think Ruby could change something so fundamental as dynamic => static typing and still retain its beauty?

The only static typing solution I've seen for Ruby is Sorbet, and it's... not beautiful.


Crystal [0] is what comes to mind. I've spent very little time with it, but I find the syntax very appealing.

[0] https://crystal-lang.org/


I use RBS/steep with great success to catch plenty of nil issues early, but it's similarly not great from a dev POV to have to maintain a completely separate set of rbs files (or special comments with rbs-inline). Also in my experience, modern editors don't leverage it for typing/intellisense.


Sorbet now supports inline RBS signatures, which I find a lot more readable. If you use VS code with Ruby LSP, the syntax highlighting is pretty great for the signatures too.

https://sorbet.org/docs/rbs-support


One of the main devs on Sorbet would agree: https://blog.jez.io/history-of-sorbet-syntax/


Based on what Ive read [1], Sorbet was born out of very specific circumstances at Stripe, in the same sort of way that go was at google. I think it missed the mark due to it being a specific tool for specific usecases instead of an "open source project for the general public" first.

I love ruby but I do look forward to having a good option for types at some point. The community makes up for lack of types by adding more tests to their test suite, which is nice but I'd love to layer some encoding into the codebase itself and save the CI time.

[1] - https://blog.jez.io/history-of-sorbet-syntax/


Static type-signatures are inevitable in general. You can see this by how even the Ruby documentation has to make up silly ad hoc notation like "→ array_of_strings", "→ matchdata or nil" etc.

(Random example): https://docs.ruby-lang.org/en/3.4/String.html#method-i-lines


That's just documentation tool but the method is actually already statically typed by ruby.

I'm not sure why they don't link that in the documenation but I beleive it is something the RDoc mainer wants to do.

  def lines: (?string? separator, ?chomp: boolish) -> Array[String]
           | (?string? separator, ?chomp: boolish) { (String line) -> void } -> self
https://github.com/ruby/rbs/blob/master/core/string.rbs


As someone coming from Ruby to TypeScript, I find types cumbersome, verbose, complex, and not of much use. I have been writing and reading TS for the past six months. What am I missing?


I have been building web apps for long enough to remember when it was commonplace to SSH (or Telnet!) into the server and just vim index.php. As you can imagine, it was pretty easy to bring the site down like that, so we started doing what is now called Continuous Integration and Continuous Deployment: automated tests as a precondition for deployment.

Later, we adopted static analysis tools and code linters. This helped, but only so much could be done with the dynamically typed languages which were popular in the early internet.

As a self-taught programmer with no college degree, I started with dynamic languages: Perl, JavaScript, PHP, Ruby. I viewed the statically typed languages (and the programmers who could wield them) with reverence and awe. C, C++, Java, these were “real” languages that required big brains, and I should stay in my dynamically typed playpen. But as I matured, my understanding shifted: dynamic languages require hubris, require belief that you can keep an entire complicated codebase in your head with perfect recall. Statically typed languages, it turns out, invite humility.

With a static type system, each step in a program’s lifecycle can be a little contract with itself. Break that contract and the language will tell you exactly how and where. These languages can provide immediate feedback to the developer about a program’s correctness before it is even run. Bridging the gap between all of the existing dynamic code (and the developers who wrote it) and the statically typed utopia lies so-called gradual type systems such as TypeScript.

I like to use a meteorological analogy here: if JavaScript is “wintry mix,” then TypeScript lowers the temperature just enough to build a snowman.


heh, i got the opposite experience going from static to dynamic.


Typescript is a bad introduction to the world of static types in a lot of ways. Typescript is incredible for what it is doing, but still, at its core, laying down a static type system on top of a language ecosystem that was dynamic for years is fundamentally just, well, a bit whacky compared to a language ecosystem that was static from the beginning.

I've been doing Typescript now for about 9 months, so I wouldn't call myself an expert in that, but I also have decades of experience in many other dynamic and static languages (including Haskell), so I can say with confidence that a lot of features in Typescript are to solve problems unique to the Javascript world, and then there are the features in Typescript that are there to solve problems in the other Typescript solutions, and all-in-all while it has great utility and has many fantastic features it just isn't possible to completely overcome the fact that it's a static type system, on top of a dynamic type system.

I've seen a number of posts to the effect of "I'm coming from Typescript and learning Go, how do I do X" and so often the answer has been "Even in Go, even with its very simple type system by static language standards, the answer is that you don't do X at all because X is a feature on top of a feature on top of a feature designed to deal with being on a dynamic language and when you're on a static language you not only don't deploy that solution, you wouldn't even have the problem that's the solution to except that you just created it for yourself by copying Typescript too closely in some other way." A simple example being you don't ask how to type a map/dict/etc. in a normal static language based on the contents of the "type" value, you just declare a properly-typed value in the first place and always use that, at most converting at the edge.

Typescript is a great tool but a very unrepresentative view on how static typing works.


Very true. I would advise the parent to try something like Haskell as a hobby project. It helps you see the actual benefits of types.


Types really start pulling their own weight as the size of an application increases.

In order to catch problems in dynamic type languages you end up needing a bunch of additional tests to, ironically, verify the expected type. And even then, those tests don't and can't tell you how a method is actually used throughout the program.

Consider the following class

   class Human
     def initialize(name)
       @name = name
     end
   end
Now imagine you want to refactor this class to something like this

    class Human
      def initialize(first, middle, last)
        @fullName = "#{first} #{middle} #{last}"
        @first = first
        @middle = middle
        @last = last
      end
    end
All the sudden you've got a problem on your hands. You have to find everywhere that referenced `name` on a `Human` object (And don't mess that up, it could be `name` on the `Pet` object) and change them over to full name, or figure out if they are doing something tricky like trying to extract the first name from `name`.

Types make refactoring this sort of code somewhat trivial. You simply change the fields and let the compiler tell you ever position which relied on that field.

This extends into all sort of circumstances, like letting the user of a method know what types are expected. For example, the above ruby code doesn't really guarantee that `first` is a string. In fact, it could be an int or even an object and the code would likely handle it just fine. Types expose interface contracts in a quick and easy way for programmers to understand what they are dealing with.


The classical counterargument to this is that, if you have good test coverage then eliminating @name should lead you directly (via failing tests) to where the name field was being used. This works especially well in codebases which enforce what I tend to call "pseudo"-type systems, for example via clojure's spec and Racket's contracts. Where the shape of data is enforced structurally at runtime.

To be honest, the argument in favor of static typing that I find more compelling is the IDE argument. It definitely is a much richer experience browsing code in an IDE with the benefit of hovering over values and knowing their type, ctrl-clicking to go to where something is defined, et cetera. The equivalent of this interactive experience for dynamically-typed languages was supposed to be the REPL. But I feel like true REPL-driven development has mostly fallen by the wayside, and most environments don't have great support for it.


Yes, the type system basically replaces a degree of unit tests. You no longer need unit tests that are basically just type checking. And it's more comprehensive too. It's much easier to have incomplete test coverage without knowing it than an invalid type system. With such a type system, the app will fail to compile. Of course, you still need unit tests for many other things, but the type system does remove a class of them.

Whether typechecking or unit tests is "better" is really a question of taste.


It’s an interesting example, knowing when to make a breaking change is really tricky in codebases like these.

You could avoid it by leaving “name” and just adding the additional fields. Maybe that’s the “right” thing to do if you have a ton of consumers and spotty test coverage. But if there’s a lot of fragile code out there (parsing “name” in subtlety different ways, etc.) it’ll never be fixed/improved. Things can get gnarly over time because there’s multiple ways to do something, and everything starts to feel like “legacy code”.

I tend to think that for private codebases, it’s important for breaking changes to be easy.


> let the compiler tell you

That's really the crux of it. Types are a way to talk to the compiler and it will be your primary target. Humans will also benefit somehow, but it's secundary and they won't be the one who'll give you a tough time.

I see it:

- strict types guarantee the compiler is happy but you'll need to bend yourself to make sure it actually matches your intent

- loose types help you properly express your intent, but you're one the hook to make sure the interpretor does what you said.


If your only exposure to static typing is six months of TS, what you are missing is experience. You're still on the learning curve and thus the cognitive load of explicit types is high, but with time the opposite becomes true.


Typescript is not suitable for all applications. I also transitioned to Typescript from python some years ago and the extra information about "intent" provided by types made a world of difference to me when reading code written by other people. Type information is so valuable in a team of 3+ developers and when a rest api has at least 5+ resources. If your application or team size are any less, the benefits of typescript might not be obvious. I think that could be what you're experiencing.

In a team, it is just so much easier to come across a "typed" function as opposed to an untyped one. You need to read the entire function to know what it is about.


Totally agree. I've found that people who don't understand the value of types are usually solo devs


Have you sat down to actually learn them? If you're still guessing at them, they're going to be hard. I'd recommend https://type-level-typescript.com/


Typescript is structurally typed, not nominally typed like C# or C++. Lots more type Olympics.


Types in TS can indeed become very complex (depending on their usage of course) and it might not be the best example of the benefits.

I personally think that simpler Rust is a better example of the benefits static typing (or maybe something like Gleam).


I'm on the fence. On the one hand I love the power of TS types that they can expose. On the other, I've seen a class of dev that, instead of relying on simple types, will try and make a monstrosity type that does unholy things.

I feel a little bit about it like I feel about RegEx. Small and simple are good, but once you start diving into the entire catalog of regex capabilities for a single expression you've made a mistake.


> On the other, I've seen a class of dev that, instead of relying on simple types, will try and make a monstrosity type that does unholy things.

Totally agree, however that love of complexity will just squeeze into something else had they not had types to have fun with.


Id guess its a combination of good editor support for implied types (eg vscode is first-rate at this), plus you likely lean heavily into the test suite when you could likely remove some tests and replace them with better types.


I've only used TS a bit, but I find the typing (and everything else) to be vastly more difficult/convoluted than in Go. Though, using Deno does help a lot (not necessarily with typing though).


Some people prefer to find bugs after deployment, I suppose.


I think Ruby is really great at what it tries to do. The only "problem" with it is that python kind of sucked the air out of the room and ruby got shoved into a little niche.

These languages are really quite similar in many ways, but their domains ended up diverging. With python becoming the layman / scientific / learning language of choice, ruby has been pigeon holed into mostly web development.

Both are really easy to pick up and learn for somebody unfamiliar with CS concepts and I personally find the ruby syntax far more intuitive.

We have a lot more options now. For a while people tried to use python and ruby as glue / systems programming languages, but with golang and rust you have really good and more performant options in that space. And as you say the tooling has improved massively, so the hurdle of moving on to a more "rigid" language is less than it ever was.

I still really like ruby, and I think rails is still a powerhouse due to solving so many real world problems in a really complete package, but the lack of adoption outside of that niche has left it dwindling in popularity.


Python syntax is more intuitive for someone who initially learned C or Java, and for mainstream developers a point in its favor.


LSP (Language Server Protocol) was the final nail in the coffin of Emacs for me.

VSCode was "good enough" for pretty much every language with LSP at that point, I did't even bother with Jetbrains ides outside of work after that.

And when Obsidian replaced org-mode for me, I deleted my .emacs directory from my dotfiles repository.


> LSP (Language Server Protocol) was the final nail in the coffin of Emacs for me.

It was the opposite for me. Emacs + LSP + many other common conveniences all bind together so beautifully and efficiently that I can't imagine using any other IDE at this point.


Indeed. I'm a long time Emacs user (emacs-nox in the terminal). After spending a day getting LSP and eglot working, I'm loving the "IDE" experience. Reliable indentation, auto-complete, intelligent var renaming, real-time(ish) warnings and error messages, etc, all the good stuff. I'd been ignoring IDE features in Emacs for years, thinking I didn't need them, but I have to admit they're a luxury I don't want to give up.


And I have to say that the whole trope of "Emacs may be able to do anything but you have to configure a lot to get it to work" has has got to be pure exaggeration at this point with things like eglot. I had the most painless experience setting up LSP for Java (among many others).


It is in fact pretty true with C++.

Getting everything set up for jump to definition and find references to work with an existing code base ... can be a journey.

If you are at a Visual Studio / XCode shop (where these things have been set up and work) you will definitely be swimming against the stream trying to get emacs to "speak" that codebase.


Same, Emacs is improving at a rapid rate thanks to its adoption of LSP and Tree-Sitter. Performance is very good, but the async story needs to become better.


Same. It's easy to setup and use. As is gptel, aidermacs, and claude code ide.


It's the muscle memory. I tried really hard to use things like vs code that do a lot of things better (or at least more automatically) and always end up more efficient in emacs.

Hopefully emacs can catch up.


> jumping to definitions and implementations

This is undervalued. So frustrating in ruby that this doesnt exist or at least isnt easy.


Fully agree. Had to work in the past with ruby. Loved it but type errors during runtime where a thing and therefore I would never use ruby in production again.

I use kotlin nowadays…


I used Kotlin before it was popular and people laughed at me... And now I use TypeScript...


Kotlin is lovely to work with but holy hell is it slow to iterate on.


What does "slow to iterate on" mean?


Lack of types is one thing that turned me away from Elixir when I was trying to learn it.

I didn't know how to think about the types so I wanted some way to annotate them to help think through it, but went through it. And then the compiler complained at me I was passing in the wrong type to a function. I mean yes thanks? But also give me a way to figure that out BEFORE I try running the code.


Try Gleam!


Typing not being a natively ruby thing makes all efforts to type the language in place seem second class. Ruby needs a typed variant that compiles down to type less Ruby.


This was always true, to be honest. Statically typed languages have always been better. Free IDEs such as Eclipse have been available for a long time. Good JVM languages such as Scala have been available for a long time.

If only the Ruby ecosystem had adopted Scala instead of Ruby, with cutesy books and eccentric underscored personalities, history might have been different.


I’m honestly still stunned at the self-implosion of the Scala community… can’t think of any other language that threw away such quite unexpected success at an industry level. Apart from the toxic community, not trying to challenge Python for supremacy in the scientific computing/data analysis space seems like the major mistake, given it was for a time the lingua franca of data infra (Spark, Scalding etc).


You _can_ largely ignore the toxicity. Don't give toxic individuals attention, and they go somewhere else to stor the pot.

Just debate the ideas with the merits in the source code, ignore the haters, and be kind and helpful. It's not difficult to do.


Oh for sure, I'm not too stressed by it -- but I think the ship has sailed on the chance for mainstream Scala adoption. Perhaps it was always delusional, but there was a period when it really seemed like Scala had somewhat of a chance to be the Ruby replacement and become one of the main backend languages (after the Twitter rewrite to Scala, when Foursquare, Meetup and various other startups of that generation were all in on the language); then there was a generation where at least it was the defacto language for data infra. Now, I'm not even sure if many major companies are even using it for the latter case.

Mainstream adoption isn't everything and I still mostly use Scala for personal projects, but it's such a different world working in a language where the major open source projects have industry backing. The Scala community, meanwhile, seems mostly stuck starting entirely new FP frameworks every other week. Nothing against that, but I don't see that much advantage to choosing Scala over OCaml at this point (if you don't need JVM integration).

Momentum appears to be behind Rust now, of course, but I've yet to be convinced. If it had a better GPU story and could replace C/C++ entirely I'd be on board, but otherwise I want my everyday language to be a bit closer to Python/Ruby on the scale against C/C++.


Not sure how to think about that idea.

Ruby was a great little niche language until Rails showed up.

Scala did not exist when Rails was written/extracted. When Scala was released, it did not include any of the things that made Ruby a good choice for Rails.


There's also Crystal https://crystal-lang.org/




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

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

Search: