News for hackers. Stuff that matters.
Re:Functional Programming – How and Why by TchoBeer on Monday January 02, 2023 @08:25AM (#34217569)
iirc this is notation that they adopted from rust.
Re:Functional Programming – How and Why by Jtsummers on Monday January 02, 2023 @11:09AM (#34219485)
More likely Scheme. Scheme used the ! signifier to indicate that something was being mutated. For instance `vector-copy` returns a fresh copy, `vector-copy!` copies into another vector, changing it.
Re:Functional Programming – How and Why by TchoBeer on Monday January 02, 2023 @11:17AM (#34219589)
Whether Julia took it from Rust or Scheme, or Rust took it from Scheme or Scheme took it from somewhere else, my point was that Julia did not invent this notation (this kinda sounds like an insult but it's actually not at all), and it's just a notation common a lot of functional-ish languages that allow mutation.
Re:Functional Programming – How and Why by Jtsummers on Monday January 02, 2023 @12:06PM (#34220336)
We are in agreement that Julia is not the origin of ! for this, I was just pointing out that if you want a historical take (what influenced what), Julia most likely got it from Scheme (whether it originated in Scheme or not is immaterial). Rust doesn't use ! to signify "This is a mutating function", it uses it to signify "This is a macro". Whereas Julia and Scheme use it as an indicator for the same thing: functions that modify their arguments. And Julia is known to have been influenced by Scheme, which existed when Julia's development started while Rust (publicly) did not.
Re:Functional Programming – How and Why by kaba0 on Tuesday January 03, 2023 @10:16AM (#34232382)
I’m fairly sure Ruby predates both of these languages by a lot and it does use the ! notation for similar things.
Re:Functional Programming – How and Why by brundolf on Monday January 02, 2023 @12:54PM (#34221130)
In rust ! signifies invoking a macro, so it couldn't be used like this in a function name even if you wanted to. Also, Rust allows you to notate immutable/mutating/owning for each individual argument type, so there wouldn't be much point:

  fn do_thing(a_owned: Foo, b_mutating: &mut Foo, c_immutable: &Foo) {
There is a convention to separate the two kinds of functions (consume and return in some, mutate in others), but that's the only commonality