frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Start all of your commands with a comma (2009)

https://rhodesmill.org/brandon/2009/commands-with-comma/
232•theblazehen•2d ago•67 comments

OpenCiv3: Open-source, cross-platform reimagining of Civilization III

https://openciv3.org/
694•klaussilveira•15h ago•206 comments

Hoot: Scheme on WebAssembly

https://www.spritely.institute/hoot/
6•AlexeyBrin•59m ago•0 comments

The Waymo World Model

https://waymo.com/blog/2026/02/the-waymo-world-model-a-new-frontier-for-autonomous-driving-simula...
962•xnx•20h ago•554 comments

How we made geo joins 400× faster with H3 indexes

https://floedb.ai/blog/how-we-made-geo-joins-400-faster-with-h3-indexes
130•matheusalmeida•2d ago•35 comments

Unseen Footage of Atari Battlezone Arcade Cabinet Production

https://arcadeblogger.com/2026/02/02/unseen-footage-of-atari-battlezone-cabinet-production/
67•videotopia•4d ago•6 comments

Vocal Guide – belt sing without killing yourself

https://jesperordrup.github.io/vocal-guide/
53•jesperordrup•5h ago•24 comments

Jeffrey Snover: "Welcome to the Room"

https://www.jsnover.com/blog/2026/02/01/welcome-to-the-room/
36•kaonwarb•3d ago•27 comments

ga68, the GNU Algol 68 Compiler – FOSDEM 2026 [video]

https://fosdem.org/2026/schedule/event/PEXRTN-ga68-intro/
10•matt_d•3d ago•2 comments

Show HN: Look Ma, No Linux: Shell, App Installer, Vi, Cc on ESP32-S3 / BreezyBox

https://github.com/valdanylchuk/breezydemo
236•isitcontent•15h ago•26 comments

Monty: A minimal, secure Python interpreter written in Rust for use by AI

https://github.com/pydantic/monty
233•dmpetrov•16h ago•124 comments

Where did all the starships go?

https://www.datawrapper.de/blog/science-fiction-decline
32•speckx•3d ago•21 comments

Show HN: I spent 4 years building a UI design tool with only the features I use

https://vecti.com
335•vecti•17h ago•147 comments

Hackers (1995) Animated Experience

https://hackers-1995.vercel.app/
502•todsacerdoti•23h ago•244 comments

Sheldon Brown's Bicycle Technical Info

https://www.sheldonbrown.com/
386•ostacke•21h ago•97 comments

Show HN: If you lose your memory, how to regain access to your computer?

https://eljojo.github.io/rememory/
300•eljojo•18h ago•186 comments

Microsoft open-sources LiteBox, a security-focused library OS

https://github.com/microsoft/litebox
361•aktau•22h ago•185 comments

UK infants ill after drinking contaminated baby formula of Nestle and Danone

https://www.bbc.com/news/articles/c931rxnwn3lo
8•__natty__•3h ago•0 comments

An Update on Heroku

https://www.heroku.com/blog/an-update-on-heroku/
424•lstoll•21h ago•282 comments

PC Floppy Copy Protection: Vault Prolok

https://martypc.blogspot.com/2024/09/pc-floppy-copy-protection-vault-prolok.html
68•kmm•5d ago•10 comments

Dark Alley Mathematics

https://blog.szczepan.org/blog/three-points/
96•quibono•4d ago•22 comments

Was Benoit Mandelbrot a hedgehog or a fox?

https://arxiv.org/abs/2602.01122
21•bikenaga•3d ago•11 comments

The AI boom is causing shortages everywhere else

https://www.washingtonpost.com/technology/2026/02/07/ai-spending-economy-shortages/
19•1vuio0pswjnm7•1h ago•5 comments

How to effectively write quality code with AI

https://heidenstedt.org/posts/2026/how-to-effectively-write-quality-code-with-ai/
264•i5heu•18h ago•216 comments

Delimited Continuations vs. Lwt for Threads

https://mirageos.org/blog/delimcc-vs-lwt
33•romes•4d ago•3 comments

Introducing the Developer Knowledge API and MCP Server

https://developers.googleblog.com/introducing-the-developer-knowledge-api-and-mcp-server/
64•gfortaine•13h ago•28 comments

I now assume that all ads on Apple news are scams

https://kirkville.com/i-now-assume-that-all-ads-on-apple-news-are-scams/
1076•cdrnsf•1d ago•460 comments

Female Asian Elephant Calf Born at the Smithsonian National Zoo

https://www.si.edu/newsdesk/releases/female-asian-elephant-calf-born-smithsonians-national-zoo-an...
39•gmays•10h ago•13 comments

Understanding Neural Network, Visually

https://visualrambling.space/neural-network/
298•surprisetalk•3d ago•44 comments

I spent 5 years in DevOps – Solutions engineering gave me what I was missing

https://infisical.com/blog/devops-to-solutions-engineering
154•vmatsiiako•20h ago•72 comments
Open in hackernews

Ruby Symbols

https://tech.stonecharioteer.com/posts/2025/ruby-symbols/
64•stonecharioteer•2mo ago

Comments

Mystery-Machine•2mo ago
Symbols are a foot gun.

> Symbols aren’t interchangeable though.

    user = { name: "Alice", age: 30 }
    puts user[:name] # Alice
    puts user["name"] # nil

I'm 100% convinced that every Ruby developer has at least once made a bug where they tried to access a hash entry using a symbol, where the key was actually a string or vice-versa.

It would be great if Ruby would finally have immutable strings by default and, at that point, it would be possible to make symbols be strings. This would prevent any such user[:name] vs user["name"] bugs while not breaking any other functionality. And also keeping the memory "optimized" by reusing a single immutable string.

Lio•2mo ago
Sure, we wouldn't have ActiveSupport::HashWithIndifferentAccess if it wasn't an occasional issue.
shevy-java•2mo ago
Agreed. However had it should also be mentioned that this originated from rails.

Many bad things originate from the rails ecosystem. (Arguably some good too, but I am very pessimistic ever since shopify's recent powermove and DHH side-line commenting off-the-fence while being on shopify's board.)

Lio•2mo ago
Rails has paid my salary for the best part of 20 years on and off. I'm OK with it. ;)
byroot•2mo ago
HashWithIndifferentAccess was added because back in the day symbols were immortal, hence could not be used for request parameters.

It no longer make sense today, and any new use of it is a smell.

shevy-java•2mo ago
> I'm 100% convinced that every Ruby developer has at least once made a bug where they tried to access a hash entry using a symbol, where the key was actually a string or vice-versa.

Yeah, that is true. It adds a cognitive load onto the ruby developer writing the code as well. Personally I prefer symbols as keys in a Hash, mostly because I like symbols, I assume it may be faster usually (this depends on factors, such as how many symbols one uses, the garbage collection kicking off and so forth, but by and large I think for most use cases, Symbols are simply more efficient). We also have abominations such as HashWithIndifferentAccess; Jeremy wrote an article why that is not good (indirectly, e. g. the article he wrote was about Symbols more, their use cases and differences to Strings, but from this it follows that HashWithIndifferentAccess is not a good idea. While I agree, I think some people simply don't want to have to care either way).

If I need to query a hash often, I tend to write a method, and the method then makes sure any input is either a string or a symbol for that given Hash.

> It would be great if Ruby would finally have immutable strings by default

But it has. I still use "# frozen_string_literal: true", but if you omit it, the Strings are frozen by default. People could set "# frozen_string_literal: true" in a .rb file if they want to retain the old behaviour.

> it would be possible to make symbols be strings.

But Symbols are not Strings. And bugs based on x[:foo] versus x['foo'] are always going to happen. They are very easy to avoid though. I don't really run into these in my own code, largely because I settled on symbols as keys for a Hash.

> And also keeping the memory "optimized" by reusing a single immutable string.

But a Symbol is not a String. Not even an immutable String. I understand what you mean (and internally it may be that way already, actually), but it is not a String.

Mystery-Machine•2mo ago
I also prefer symbols as keys in hash. It just looks more aesthetically pleasing. :) I think the optimization string vs symbol is negligent in most of the apps. If you need that level of optimization, you should probably switch to Rust.

> If I need to query a hash often, I tend to write a method, and the method then makes sure any input is either a string or a symbol for that given Hash.

This is terrible. This is the exact opposite of what Ruby is trying to achieve: developer happiness. You basically implement "symbol is a string" for hashes (aka HashWithIndifferentAccess).

> But it has. I still use "# frozen_string_literal: true", but if you omit it, the Strings are frozen by default.

This is not the case. If you omit "# frozen_string_literal: true", the strings are mutable, in all versions of Ruby, even in Ruby 4.0, which will be released on 25 Dec.

> But a Symbol is not a String. Not even an immutable String. I understand what you mean (and internally it may be that way already, actually), but it is not a String.

If it walks like a duck and quacks like a duck... Who cares? What's the difference it makes for you whether symbols and string are interchangeable? Show me one valid use-case where having symbols and strings being different (user[:name] vs user["name"], or attr_reader "name") is useful.

lloeki•2mo ago
When one consistently uses symbols for keys and strings for data then when you notice a `user[<String>]` it is a very visible, obvious mistake.
an0malous•2mo ago
That’s not much more of a foot gun than:

    user[“1”] = user[1]
Symbols are always taught as a first class object in Ruby, not just syntactic sugar for accessing hashes. “foo” does not equal :foo
IshKebab•2mo ago
The foot-gun there is dynamic typing, not symbols.
thomascountz•2mo ago
Here's a fantastic writeup about frozen strings in Ruby and the upcoming changes: https://byroot.github.io/ruby/performance/2025/10/28/string-...
tsm•2mo ago
I'd guess that the majority of people who've made a bug like this got started on Ruby via Rails, where many hashes are HashWithIndifferentAccesses.

HWIAs are convenient, but they do confuse the issue.

rubyfan•2mo ago
Rails makes this more confusing with HashWithIndifferentAccess[1]. People coming from Rails are often confused by this when working with straight ruby and this kind of hash access doesn’t work.

1. https://api.rubyonrails.org/classes/ActiveSupport/HashWithIn...

masklinn•2mo ago
OP is really tying themselves into knots.

Symbols are special cased pseudo-strings for langages which have either extremely inefficient strings (erlang) or mutable ones (ruby). That’s about the extent of it.

Python or Java don’t really have a use for them because their strings are immutable, and likely interned when metaprogramming is relevant (e.g. method or attribute names).

Joker_vD•2mo ago
What about LISPs? They have atoms too.
__s•2mo ago
Generally mutable strings there too, like Ruby
bashkiddie•2mo ago
Could not read OP, clownflare is down.

> Symbols are pseudo-strings

Can guess by LISP: Symbols reside in the symbol table, which is global scope. Strings reside in the variable tables, subject to local scope.

It is two different storage mechanisms

> inefficient strings

Ruby does not care for efficiency, so there is no point to argue for symbols vs string performance

masklinn•2mo ago
> It is two different storage mechanisms

An irrelevant implementation detail. Interned strings are also stored globally, and depending on implementations interned strings may or may not be subject to memory reclaiming.

> Ruby does not care for efficiency, so there is no point to argue for symbols vs string performance

Which is why Ruby's having symbols is associated with mutable strings, not inefficient strings.

And there's a gulf between not caring too much about efficiency and strings being a linked list of integers, which is what they are in Erlang.

15155•2mo ago
> Ruby does not care for efficiency, so there is no point to argue for symbols vs string performance

Symbols existed entirely for performance reasons and were once never GC'd: this is absolutely Ruby "car[ing] for efficiency."

Today, Ruby's Symbol is GC'd (and is much closer to 'String' in practicality) but still has enormous impacts on performance.

davexunit•2mo ago
This is silly. The semantics are entirely different!
phoronixrly•2mo ago
How so? Quite literally symbols are used as an immutable string with a shorter syntax. So much so that I've been finding their literal constraints limiting lately.
giraffe_lady•2mo ago
Almost the entire value of symbols separate from strings is at the level of programmer communication rather than PL semantics.

It tells a reader of the code that this term is arbitrary but significant, probably represents an enmeshment with another part of the code, and will not be displayed to any user. When seeing a new term in code that is a lot of the things you're going to need to figure out about it anyway. It's a very valuable & practical signal.

If you need to mutate or concat or interpolate or capitalize or any other string operation it, it probably shouldn't be a symbol anymore, or shouldn't have been to start with.

masklinn•2mo ago
> Almost the entire value of symbols separate from strings is at the level of programmer communication rather than PL semantics.

That's the opposite of reality. Symbols are necessitated by PL semantics, which is why languages which don't have those problematic string semantics tend to not bother with symbols.

> It tells a reader of the code that this term is arbitrary but significant

That you can do that with symbols is not why they exist (you can need to associate additional semantics with pretty much any first or third-party type after all, that's why the newtype pattern is so popular in modern statically typed languages).

And it's not like you need formal symbols to do it in the first place. For instance like an other nearby commenter in Python I do that by using single and double-quoted strings, having taken up that habit from Erlang (where symbols are single quoted and strings are double quoted).

giraffe_lady•2mo ago
> And it's not like you need formal symbols to do it in the first place.

I mean we don't need any of this shit. Go take a long bath and then write some assembly I don't care. Symbols are a useful tool in some languages, for the reasons I described. That you're creating ad hoc quoting conventions to recover part of the functionality of this feature in languages that don't have it is a pretty strong signal I'm correct! Opposite of reality my ass lol.

masklinn•2mo ago
> This is silly.

Oh my bad, great counterpoint.

> The semantics are entirely different!

They're not. A symbol is an arbitrary identifier, which can be used to point to system elements (e.g. classes, methods, etc...). These are all things you can do just fine with immutable interned strings. Which is exactly what languages which have immutable interned strings do.

You'd just have a broken VM if you used mutable strings for metaprogramming in Ruby, so it needs symbols. Both things it inherited from all of Perl, Smalltalk, and Lisp.

byroot•2mo ago
Ruby always had immutable (frozen) strings, so no, this never was a reason for Symbols existence.
dragonwriter•2mo ago
They aren't interned frozen strings (unless they were symbols; String#intern was, and still is, an alias for String#to_sym, and String#freeze did not and does not imply String#intern or String#to_sym), and it also (even for literals) took an extra step to either freeze or intern them prior to Ruby 2.3 introducing the "# frozen_string_literal: true" file-level option (and Ruby 3.4 making it unnecessary because it is on by default.)

Amusingly, string literals interned by default in 3.4 or because of the setting in earlier >2.3 Rubies are still (despite being interned) Strings, while Strings interned with String#intern are Symbols.

byroot•2mo ago
> They aren't interned frozen strings

Doesn't matter. The parent claim was:

> You'd just have a broken VM if you used mutable strings for metaprogramming in Ruby

From day one it was possible to freeze strings used in metaprograming. I mean Ruby Hashes do that to strings keys.

> Ruby 3.4 making it unnecessary because it is on by default.

That's incorrect: https://byroot.github.io/ruby/performance/2025/10/28/string-...

dominicrose•2mo ago
Whenever Perl encounters a string literal in the code (especially one used as a hash key or a bareword), it often "interns" it. This means it stores a single, canonical, read-only copy of that string in a memory pool.

That's the core idea, and then Ruby has surface stuff like the symbol syntax and class. I'm pretty sure it's fine to use strings as hash keys though if you like.

bhaak•2mo ago
> I'm pretty sure it's fine to use strings as hash keys though if you like.

Sure. They are just less efficient as hash keys.

Although now the distinction blurs with frozen strings (and the string literals being frozen by default switch).

dragonwriter•2mo ago
Ruby has always had frozen strings (what it didn't have was interning of string literals, which is what the somewhat-poorly-named "# frozen_string_literal: true" option available from Ruby 2.3 and made default in Ruby 3.4 actually does, which makes string literals basically equivalent to symbol—but, not actually symbols, unlike, in another example of suboptimal naming, what would happen with String#intern, which has existed longer to intern strings, but is actually just an alias of String#to_sym.
raincole•2mo ago
Symbol is the only feature I miss after switching to Python. It makes code so much more readable to distinguish keys and normal strings.
masklinn•2mo ago
Much like yccs27 above, I do that using single and double quoted strings (a habit I got from Erlang).
User23•2mo ago
That’s really not true for Lisp.

Ruby, like its predecessor Perl, is one of the finer examples of Greenspunning and shows a lot of Lisp influence.

Unfortunately I can’t read the actual submission right now due to the cloudflare outage.

stonecharioteer•2mo ago
OP here, you can read it here https://github.com/stonecharioteer/tech-blog/blob/main/conte...
masklinn•2mo ago
> That’s really not true for Lisp.

It's completely true of lisp. Lisp strings are generally mutable (although literal strings may be interned and non-mutable, or even worse mutation of literal strings may be UB). Same for Smalltalk.

kazinator•2mo ago
In a Lisp with mutable strings, like Common Lisp, those strings which are symbol names are still mutable.
User23•2mo ago
I meant more that symbols are a data structure with function and value slots. Last I knew strings, interned (which is also a Lisp reference) or not don't have that.
needlesslygrim•2mo ago
> extremely inefficient strings (erlang)

Doesn't most modern Erlang code use binaries instead of charlists? Elixir and Gleam certainly do.

kazinator•2mo ago
Lisps have unnterned symbols also.

Interning is important for symbols that are involved in I/O: being printed and read, so that two or more occurrences of the same symbol in print will all read to the same object, and so there is print-read consistency: we can print an interned symbol, and then read the printed symbol to obtain the same object.

Symbols are useful without this also. Symbolic processing that doesn't round trip symbols to a printed notation and back doesn't require interned symbols.

Symbols have a name, but are not that name.

They also have various properties, which depends on the Lisp dialect.

Classical Lisp dialects, like MacCarthy's original, endow each symbol with a property list. Another classical property is the "value cell".

In Common Lisp lists have a home package retrieved by the function symbol-package.

A variable being globally proclaimed special can be implemented as a property of the symbol.

Symbols are interned in packages, not globally, so two symbols can be interned, yet have the same name: mypackage:let and cl:let both have the name "LET", but different home packages.

Uninterned symbols with the same name can be readily made: just call (make-symbol "FOO") twice and you get two symbols named "FOO", which print as #:FOO.

The #: notation means symbol with no home package, used as a proxy for "uninterned", though a perverse situation can be contrived whereby a symbol has no home package (and so prints with the #: notation), yet is interned into a package.

Introduce a FOO symbol in the keyword package:

  [1]> :foo
  :FOO
Now import it into the CL-USER package:

  [2]> (import :foo :cl-user)
  T
Verify that cl-user::foo is actually the keyword symbol :foo:

  [3]> 'cl-user::foo
  :FOO
Now, unintern :foo from the keyword package, leaving it homeless:

  [4]> (unintern :foo :keyword)
  T
Let's print it, accessing it via the cl-user package where it is still interned by import:

  [5]> 'cl-user::foo
  #:FOO
There is quite a bit to this symbol stuff than just "interned strings".

Symbols are simply not strings objects; they have strings as a name.

Ecco•2mo ago
I think the whole article is super confusing.

A Symbol is really just a string!

Well, it's a string that will guarantee unique allocations (two identical strings are guaranteed to be allocated at the same address), which makes equality checks super fast (compare pointers directly). But pretty much just a string nonetheless...

lloeki•2mo ago
A symbol really is just an integer which happens to have a fancy name when looked at from a user's point of view.
kazinator•2mo ago
Lisp symbols have various properties; the exact set depends on the dialect. The properties may be mutable (e.g. property list, value cell).

You can certainly associate such things with an integer: e.g. value_cell[42], plist[42].

But those associations are part of the "symbolness", not just the 42.

Integers are not suitable symbols in some ways: they have a security problem.

Real symbols can be used for sandboxing: if you don't already hold the symbol, you have no way to get it.

This won't happen for integers. Especially not reasonably small integers.

What do I mean that if you don't already have a symbol, you have no way to get it? If the symbol is interned, you can intern it, right?

Not if there is a symbol package system, and you don't have access to the package in which the symbol is interned.

Now you might say, since objects are typically represented as pointers, aren't those a kind of integer anyway? Yes they are, but they are different type which doesn't support arithmetic; we can restrict programs from calculating arbitrary pointers, but we can't restrict programs from calculating arbitrary integers.

Even if we have escape hatches for converting an integer to a pointer, or other security/safety bypassng mechanisms, those escape hatches have an API which is identified by symbols, which we can exclude from the sandbox.

lloeki•2mo ago
I (and GP given their use of capitalised Symbol) was talking about Ruby symbols, which for the most part are more equivalent to their object_id than to their textual representation.

What I mean by "integer" is not "pointer", it's "natural number", in the sense that there exists only one `1` vs you can have multiple textual "foo" strings.

So it's more useful to think of symbols as natural numbers which you don't know nor care the actual value of, because as a human you only care about the label you have attached to it, but you do care about its numberness property of it conceptually existing only once.

theoldgreybeard•2mo ago
frozen string literals also have unique allocations now, so symbols are kindof redundant now
byroot•2mo ago
No they’re not.

String can be interned in Ruby, but it’s always possible for an equal string that is not interned to also exist. Hence interned strings can’t benefit from the same optimization than symbols.

You can first compare them by pointer, but on a mismatch you have to fallback to comparing content. Same for the hashcode, you have to hash the content.

theoldgreybeard•2mo ago
I'm talking about as a user of the language, not as a language designer. I have an unpopular opinion about this, but symbols are error prone and these optimizations are ultimately not worth it.
pantulis•2mo ago
> Dang it, Ruby. You never cease to amaze me!

This has been true forever.

yccs27•2mo ago
The article is a bit confusing, but I like the concept behind symbols: Basically a way to distinguish identifier names (chosen by the programmer) from user-facing strings.

The distinction between is one I've mentally adopted in other languages like Python as well. For personal projects I like to use single quotes for 'symbols' and double quotes for "strings", e.g.:

    add_label(text="Hello World!", align='center')
Does anyone else do something similar?
wild_egg•2mo ago
Single vs double quotes is also semantically significant in Ruby. Double quoted strings support interpolation whereas single quoted does not.
rubyfan•2mo ago
I almost never use single quotes unless I’m in someone else’s code that already used single quotes. And then I have to fight the urge to not change everything to double quotes just because.
masklinn•2mo ago
> Does anyone else do something similar?

I do exactly the same thing. Did you also derive it from Erlang?

Fire-Dragon-DoL•2mo ago
I have been with you for a very long time,until I recently realized how tricky the edge cases are, I cannot figure out a good rule.

A json api, should it use symbols or strings?

Json has string keys, but the api keys are chosen by the programmer.

I can't remember which edgecase,but there are another bunch I found that are tricky.

theoldgreybeard•2mo ago
I'm a ruby developer, would never dream of switching to another language as my bread and butter - but my language design hot take for ruby is that symbols were a mistake and unnecessary and the language would have been better off just using frozen (immutable) string literals for everything except for the syntax of keyword arguments.

Unfortunately we can't change it now, but generally I just don't use symbols anymore unless I absolutely have to.

nixpulvis•2mo ago
I've always been conflicted on them. I like that they allow me to be more explicit about things which are read from input or parsed out as strings vs internal parts of my program (I rarely call .to_sym), but I've also lost time to being careless and indexing hash maps with the wrong type.

Overall, I think I'm glad they exist.

theoldgreybeard•2mo ago
I've had to fix so many errors over the years due to string/symbol mismatch in function calls and/or hash access, and never once have I benefited from the extra optimizations that the guaranteed singular allocation of symbols have given me where I wasn't able to get the same benefit from a frozen string literal.

If it was up to me I'd get rid of them, but I know I have an unpopular opinion and it's really only a thought experiment.

Glyptodon•2mo ago
I still wish the Rails enums were written with slightly more object portability.