1. 2

    If you dive into the C++ hello world, follow every header, every overload and trace every iostream class that is instantiated, it feels like you are sitting on a giant complex structure that was obfuscated by the deceptively simple looking abstraction which causes hello world to be flushed to stdout.

    1. 4

      Why doesn’t the Game send an instance of Hit to the Monster instance? What in OOP stops this? Object oriented doesn’t mean that we constrain ourselves to two classes, we can still use data transfer objects.

      1. 14

        Can someone explain me the point of the rant? I don’t really understand what it’s trying to say.

        1. 84

          Every language has some core idea that inspired its creators to make it, instead of putting up with the other perfectly good languages that already existed. Sometimes, that idea is simple (“everything is an object” for Smalltalk, “everything is a cons cell” for LISP), and sometimes that idea is more complex (the way that Java is designed to scale to huge teams, or the way that Perl is “the Cliff’s Notes of Unix”).

          The author’s idea is that the core idea of Ruby is (waves hands) for making domain-specific languages. It’s not the universal syntax for expressing all algorithms, but if you have an idea for how a particular algorithm should be expressed, you can probably bend Ruby into that shape, at least within a particular class or project.

          The author’s lament is that Ruby’s core idea was never really named, and thus never advertised, and thus never formed part of Ruby’s reputation. As a result, it didn’t build up the audience of tinkerers and experimenters who could form a long-lived supportive community around it.

          Instead, what it got was Rails, which was the opposite of that core idea: instead of bending Rails into a domain-specific language for the application you want to create, the idea is to bend your application to fit within the framework Rails provides. And since Rails became hugely popular, the vast majority of the Ruby community valued that framework-style approach and Ruby just became the incidental-complexity runtime for Rails instead of an interesting thing in its own right.

          1. 11

            Brilliant summary. Well done.

            1. 4

              The Ruby-on-Rails revolution and its consequences have been a disaster for the Ruby race.

              1. 2

                Can you expand a bit on the idea that Ruby is for DSLs? I feel like I’ve heard that here and there and it always seemed like a bit of a stretch. Ruby just doesn’t have things that I would think would be critical for truly writing DSLs, such as lazy evaluation and macros.

                The vagrant config, for example, is a bunch of ruby code that calls itself a DSL but it really just feels like… writing ruby. Python, for instance, could do it just as well (see: SCons).

                1. 5

                  The instance_exec method allows for succinct DSLs whose syntax couldn’t be easily copied in other languages like Python. Basically, it allows you to evaluate blocks as if they were running in the scope of an arbitrary object’s methods — or to put it in Rubyist terms, it allows you to execute blocks with an arbitrary receiver. For (a completely contrived) example, in Python you might write:

                  conf = Library.config_object()
                  conf.config_file("foo.txt")
                  conf.worker_processes(2)
                  worker = Library.worker(conf)
                  

                  Whereas a Ruby library might read:

                  worker = Library.worker do
                    config_file "foo.txt"
                    worker_processes 2
                  end
                  

                  The interior of the Ruby block defining the worker feels in a certain sense like a DSL; these methods are not in global scope: they’re special methods that are accessible inside the block, running on an anonymous object. It’s sort of like having a domain-specific language with new keywords — config_file and worker_processes — that elegantly composes with standard Ruby.

                  Of course, really all it means is you can leave out repeated references to conf, since Library.worker makes everything run as if it’s in the scope of some method on conf (and Ruby has implicit self inside method calls, so you can write config_file instead of self.config_file). But ergonomically it can feel nice. It’s the same number of lines, but much less significant text.

                  1. 1

                    To your point: until I read this comment, I had no idea that the Vagrant config was even supposed to be any kind of DSL. It just looked like ordinary Ruby to me.

                  2. 1

                    Thank you… Didn’t even bother reading the post - love your writing style too!

                    1. 1

                      Thanks for that. I never learned that about ruby because the first and only place I tried it was (gross) codecademy, before I’d started learning how to code.

                      1. 1

                        The author’s lament is that Ruby’s core idea was never really named, and thus never advertised

                        I know this is not your point, but I have a bunch of populer old books from ruby 1.9 times such as “metaprogramming ruby” and “rspec” which disagree.

                      2. 5

                        That Ruby never gained traction for the face value of its expressiveness. I feel that this rant imply that the mix of semantic approach of Perl and the meta-approach of Lisp meeting in the right balance in Ruby have not been recognized and exploited fully to show what Ruby really is.

                        The way the author speaks about “phrase-based” reminds me of Perl, Raku, APL, dense language where you can express yourself in short understandable phrase. The author pushes the idea that this is the meaning of the mantra “Desifned for developer’s happiness”. To be happy, you have to be able to express yourself without convolution and Ruby provided that solid base and rich vocabulary to be expressive and precise.

                        1. 3

                          Me neither. Wondering if I should flag this as off-topic.

                        1. 11

                          This is a helpful article for me, thank you for posting!

                          Does Lobsters allow posts like these, though? It’s a great article, but includes an ad for a service as the last section.

                          1. 9

                            It’s a useful article until then so it’s worth letting the votes govern its relevance, imo.

                            1. 6

                              I’d say there’s a difference between “here’s some useful Rust stuff, btw use our logging SaaS at the end” and “here’s why you should use our logging SaaS”

                              1. 5

                                Author here, glad you like it.

                                I will add a conclusive sentence to make the distinction between the article and the advertisement clearer.

                                1. 1

                                  Thanks for the article, I didn’t mind the ad. Do you inspect the stack frames non-intrusively via sampling?

                                2. 4

                                  if it’s not too intrusive its okay, for example when you can read the article without the ad and you don’t miss big parts of the post

                                  1. 3

                                    Personally, I don’t mind it. There’s a lot of great and interesting content out there published by companies that usually includes some sort of “ad” for their service. I don’t want to cut that out just because they say, “hey, use our stuff” at the end. Especially because I can just ignore the ad bit and still learn something.

                                  1. 7

                                    Assemblers, what luxury! I wrote my first 6502 machine language programs directly in the Epyx FastLoad monitor on the C64 (a particularly deprived monitor at that) manually in hex. This is a little sad for me personally as I have no source code from my childhood projects to refer to. When my best friend and I got a KIM-1 as a weekend project in high school, it was easy for us to program, because we already knew the opcodes by heart!

                                    Actually being able to enter mnemonics in the C128’s MONITOR was a huge leap. Then it was TurboAssembler, and I’ve used xa65 (and now maintain it) since the late 1990s.

                                    1. 4

                                      FastLoad! Monitors! Luxury! Kids these days not knowing what they have! When I wanted to write assembly I had to enter it as raw DATA statements in a BASIC program and write it to disk!

                                      1. 3

                                        Hexadecimal was a great convenience :)

                                        1. 3

                                          Disks! What luxury! I had to record my programs on 80s mix tapes using the 1530 datasette.

                                      1. 10

                                        I’m on the side of the people who consider this a mis-overreaction out of spite. I’d like to see a mass revert… of the actual bogus commits. The would-be researchers state in their methodology description they consciously chose to submit their patches under non-UMN email addresses, so using @umn.edu as a revert criterion has a 100% miss rate for identifying bogus commits, and using no other criterion has a 0% inclusion rate. So I don’t know if this is a case of “something must be done; this is something” or something else, but I can’t find a way to frame it as a rational reaction.

                                        (Of the would-be researchers and what they did, I won’t even speak.)

                                        1. 12

                                          I think blatant violations of ethics in research deserve to be dealt with harshly, and making it the university’s problem is absolutely the right move because it is the university’s job to police their researchers. Reputation is a very hard currency for universities: it drives grants, it drives student applications, it drives where prestigious researchers want to work. Making a big dramatic stink about this threatens UNM’s reputation in the computer science field, which helps ensure the problem gets taken seriously.

                                          1. 3

                                            Greg is what we call a high-performer. Publically shaming a university for their “research” was probably a couple hours of work at most for him. And if you can do it, why not? It will likely prevent future “experimentation” from other “research groups dedicated to improving the linux kernel”.

                                          1. 14

                                            Maintaining an identity is hard, keep in mind.

                                            1. 3

                                              I’m trying to deal with something like this for myself. How much I want to separate my ‘professional’ persona from the side of me that constantly posts about being gay, NSFW things, and the like. I don’t have a good answer.

                                              1. 2

                                                Just have an anonymous account somewhere on fediverse, seems to be working fine for others.

                                                1. 1

                                                  I’m separating all my “gaming” stuff from my official open-source-contributing real name persona. Not for a real good reason, mostly it’s an experiment and literally nothing is at stake.

                                                  Here’s what I do:

                                                  • different (free) email addresses
                                                  • different domain hosters
                                                  • different server IPs
                                                  • different twitter & fediverse handles
                                                  • obviously not the same nickname
                                                  • 2 different browsers, so I don’t accidentally post as the other persona

                                                  Is this completely doxing-proof? No, someone with enough time and knowledge will make the right connections.

                                                  Am I 100% safe here? No, I’ve had to delete comments and force push to repos because I messed up (but so far I think I’ve managed to notice in <1min every time), my defense would be “needs some digging and not just a google search”.

                                                  Also I’ve posted my gaming blog’s url in channels where only friends are, so it’s only separated 100% from one side.

                                                  If I was really serious about this I’d take more care, like only using TOR or simply use another computer/VM with VPN permanently on to not have the same ip address, probably not using Google accounts on at least one of the personas - but I feel some of the steps taken in the article are taking it a little far, for needless reasons.

                                                  Like… downloading that Linux ISO from a public wifi. Not sure if the author will manage to 100% not leak to their ISP that they are connecting from that computer with that OS. And that’s the only piece of metadata I can think of right now, when using a VPN all the time.

                                              1. 24

                                                I mean, I agree, I understand where the author is coming from. But this, I am sorry to say, really does sound like someone who drank kool-aid, and I think it will be less effective for that reason. I think it is an interesting challenge for Rust people to figure out how to express the same thing in a manner that less triggers kool-aid warnings.

                                                1. 8

                                                  Yeah it sounds like the perfect ad-whitepaper.

                                                  Can we add a disclaimer about how clunky UI and web-service development feels compared to things like django ? Starting from missing crates to unbearable compile times when changing 1 line of code. And error reporting for especially the paths where you can’t really handle all failures (UI stuff with lazy initialized things). Thinking about a .clone() and restructuring stuff just to avoid it when using parts of your initial configuration struct at different places in the program, while it wouldn’t matter at all in other langs? These are parts where I dread using rust. I like the feeling of how perfect it can feel to have it written in rust. But at the same time I look at ~2Gb of build artifacts for ~300 dependencies to get a comparable web-service with 5 endpoints and a DBMS connection to run. The resulting debug ELF being ~150MB. (Or 15 minutes of release build time for ~9MB ELF)

                                                  I know the tradeoffs, I know how unfair this comparison is and how I could “just” use django. But why wouldn’t I want the speed and safety of rust? This is simply the experience I get in the end, technical reasons or not.

                                                  Maybe OPs opinion will change in ~3 years? Probably related to the types of application they write. At least to me rust is still in my heart after 6 years and still in my toolbox. But I enjoy writing programs in languages where I’m not forced to care about every None or Err. Where compilation time is instant and I’m not the early adopter of crates that are pretty much finished in other languages.

                                                  1. 6

                                                    These complaints (which are real) feel pretty similar to issues I’ve run into when using Django. Dealing with dependencies in Django projects, like in any python project, can be a time-consuming pain in the ass. I’ve definitely seen Django projects many megabytes in size - not to mention the size of the Python interpreter you need to run them (not to mention debugging problems with selecting the right Python interpreter version!). To be clear, I personally like Django, and think it’s an eminently reasonable choice of web framework. But I don’t think it’s dramatically better than the Rust frameworks I’ve used.

                                                    But I enjoy writing programs in languages where I’m not forced to care about every None or Err.

                                                    If you’re not forced to care about None and Err values explicitly in the code, you’ll be forced to care about them when you try to do an operation on some value that turns out to be a null when you weren’t expecting it and throws a runtime error. Having to manually unpack an Option<T> replaces TypeError: Cannot read property 'x' of undefined (or whatever your language’s equivalent is).

                                                    1. 2

                                                      I think rust triggers my struggle for perfection. I can simply ignore failures in django by letting it crash and dealing with it or leaving it as a crash. While in rust I always try to make it correct and handle all of these cases as I see every possible “exception” point. And this is the part where just setting up a mockup in django for some lightweight ERP system or data management feels so light, so easy. And as my naming suggests I probably won’t build something that requires high correctnes this way in django. But in rust I get the feeling that there’s no other way than the correct, perfect one, if you don’t want to unwrap() at every point.

                                                      Declaring some stuff as lateinit var in android and then later initialize it. Just bind it when you need it and it’ll probably be fine, don’t handle each possible case of “it should be initialized because we’re past point X but you can’t be sure”*. Something you won’t do in rust and where the same program in the same setting would be just so ugly.

                                                      This also comes down to the last point: Many things like UI just feel clunky because they’re build for different languages or rather idioms. It’s ok to just write loosely coupled UIs in android that get initiated from design sheets during runtime and then bind to them. But you won’t do that in rust. You’ll probably use iced and bake the whole UI declaration and logic into one program that compiles as one big thing (thus taking seconds for a println!() change). Yes its a nice all-in-one binary that runs pretty correct. But I don’t get the feeling that I’ll ever do something serious with this kind of coding style for UI based systems. That I’d have to invest so much more work to reach the same kind of completeness (feature wise, behaviour, look’n feel), reaching the point where its not feeling like a mockup that you won’t ever show to someone that isn’t a CS grad. As if someone would try to write a CMS in assembly, while having seen how fast you get this up with django/rails/cake-php/..

                                                      *And yes I hate those NullPointerExceptions and state-loss on rotation. But I like at how many places I don’t have to code around possible nulls. Even though I’m using kotlin to get a little more awareness of possible nulls.

                                                      1. 1

                                                        Returning Optional[T] in python function signature helps your syntax checker mark your code with a warning. Syntax checkers are even clever enough to stop warning you after you add the None check. Never had an issue with evaluating None.x after python 3.6.x

                                                        1. 2

                                                          Yup, and this is effectively the same thing as matching on an Option type in a language like Rust with ML-style types, just retrofitted onto Python’s existing syntax and semantics. Using a type checker in modern Python makes you have to care about Nones, because that affects whether the type-checker will pass or fail on your code.

                                                          1. 1

                                                            I actually enjoyed this behavior for several years while using kotlin with the jetbrains community edition IDE. Very nice to see other languages adopting it where their type system allows.

                                                      2. 5

                                                        I think the question of ‘what is my alternative?’ is a helpful framing. If Django is a reasonable alternative, you probably shouldn’t be using Rust for all of the reasons you just listed and more.* I really like using Rust because my only alternative is C++, and C++ is…

                                                        • Not that you should 100% be using Django, but something in the Django, Rails, Go, etc family would be a better fit.
                                                      3. 3

                                                        not joking, you worded perfectly what i was imprecisely thinking

                                                      1. 1
                                                        1. 4

                                                          This is neat, though what would be more interesting to me (and what I’ve thus far been unable to find) is whatever discussion (of this particular code/merge) took place on the mailing list.

                                                          From a quick skim it looks like the rust code is set up to panic on allocation failure in at least some scenarios – that’s certainly a thorny issue language-wise, but if it remains that way does that just relegate rust to second-class status, making it unable to implement a module capable of returning ENOMEM when appropriate? Have there been any breakthroughs on solving problems of interop with the rest of the kernel using very C-specific APIs like struct list_head or the tracepoint macros?

                                                          Getting some basic code compilable and integrated into the build system is cool and an important step, but it still seems like there are much bigger and more difficult problems to address before there’s any clear path to it being viable for serious, widespread use in the Linux kernel.

                                                          1. 6

                                                            The panicking error handler is only for the alloc crate. If you allocate memory directly from the allocator, you can handle failures however you like. Rust is also adding fallible Box::try_new and Vec::try_reserve, so it should be possible to handle allocation errors gracefully even if you use the standard containers.

                                                            And finally there’s catch_unwind to catch all panics. That will most likely be necessary anyway, just in case the code trips on something else like arr[bad_index].

                                                            1. 1

                                                              I remember having to remove exception support and runtime support when developing a custom kernel module in c++, is that not the case with rust?

                                                              1. 1

                                                                Rust doesn’t have exceptions (panics are not an equivalent mechanism). However, you can choose to configure a crate to abort on panic instead of panicking the current thread and unwinding the stack, which removes the small bit of code necessary to support unwinding. In that case though, panics are no longer able to be handled, and instead kill the program entirely.

                                                                1. 1

                                                                  Thanks, though I’m not sure how we can handle a panic during module initialization as resources need to be released in lifo order in case one of them fails. This might cause module initialization to hang and we won’t be able to unload.

                                                          1. 4

                                                            So, why do you need containerisation for a personal blog?

                                                            1. 2

                                                              so that you can build and push to deploy. Oh wait.

                                                            1. 3

                                                              I am not offended by fizzbuzz. It gives me the opportunity to make the most over-engineered fizzbuzz ever and take the screener to alice in wonderland and back.

                                                              1. 6

                                                                Yeah, I kind of like to do something like the following. I don’t know whether it’s actually good policy, but such questions annoy me. And the interviewer quite likely doesn’t know how some parts work.

                                                                #include <stdio.h>
                                                                
                                                                #define F "fizz"
                                                                #define B "buzz"
                                                                
                                                                char is[4], *s[] = {is, F, B, F B};
                                                                
                                                                int main(){
                                                                  for (int i=1; i<=100; ++i){
                                                                    sprintf(is, "%d", i);
                                                                    printf("%s\n", s[0x1241843>>2*(i%15)&3]);
                                                                  }
                                                                }
                                                                
                                                              1. 6

                                                                This looks cool, but I don’t want a bunch of dependencies on random people’s GitHub URLs in my build scripts??

                                                                1. 3

                                                                  If you don’t like to include urls, you can install the packages locally. If you don’t like random people, you’re all out of luck.

                                                                1. 5

                                                                  Drop column will fix a lot of issues regarding ORMs. For example: Alembic migrations will not error out anymore. That was the sole reason I switched to postgres in a few projects.

                                                                  1. 7

                                                                    It’s your code. If it crashes, you fix it. We like this idea because it pushes developers to deliver higher-quality code. The dread of taking those middle-of-the-night phone calls provides a little extra incentive to take another pass through your work before you ship.

                                                                    Is that… even legal?

                                                                    1. 14

                                                                      Found the European!

                                                                      TL;DR: This is very likely illegal in the EU, you can’t do that to employees. Part of our SRE team is in Sweden, and we had to to a lot of threading the needle to meet Swedish laws about right to rest when we set up on-call rotas. I would assume “you are always on call” would be illegal in most non-US countries.

                                                                      1. 2

                                                                        Thanks, I thought so.

                                                                      2. 5

                                                                        Yes, there is no law to absolve workers of responsibility.

                                                                        1. 3

                                                                          Why would it be illegal?

                                                                          1. 8

                                                                            you can’t have all your employees on call all the time

                                                                            1. 14

                                                                              I parsed this as I’ve seen it: each team has its own on-call rotation.

                                                                          2. 1

                                                                            I don’t think this literally means they have a pager system that runs git blame on stack traces and pages the poor soul that touched it last (or even worse, just pages an entire team simultaneously).

                                                                            I took this to be an allusion to some permutation of full service ownership — as in, the engineering team responsible for building a service also maintains on an on-call rotation to take responsibility for that service in production. This is in contrast to the older pattern of “engineers chuck code over the wall into production and go home, while the SRE/ops folks deal with whatever hell rains down at 3AM”. I don’t see why this would be illegal, unless pages were happening so often that folks couldn’t sleep / live a life.

                                                                          1. 3

                                                                            Not really a C expert, but I try to use std::istream whenever C++ is available while parsing anything that needs speed. Seek until ‘v’, peek ‘e’, ‘r’, ‘t’, ‘e’, ‘x’, ’ ’, then read bool ohyeah = in>>x>>y>>z; No string scans, no gulping the file, just plain old single pass.

                                                                            1. 7

                                                                              a terrible take from a person who is full of 💩 https://campaign.gavinhoward.com/platform/

                                                                              the author is too shortsighted to see how shortsighted they are 🤷

                                                                              https://twitter.com/wbolster/status/1365983352835231744?s=19

                                                                              1. 15

                                                                                To be fair, author’s extremist views on christianity, society, medicine or politics doesn’t make him wrong on another unrelated subject. “You should first fix bugs instead of switching to a less portable language” is not a wrong thing to say. “You should not break other people’s operating systems” is not a wrong thing to say. Rust may be superior in terms of end product quality, but it is not the default choice for every situation.

                                                                                1. 17

                                                                                  “don’t write bugs” doesn’t work despite 40 years of industry experience with unsafe languages. see other comments.

                                                                                  the piece is littered with opinions about what others should do (with their spare time even), while at the same time maintaining poor people shouldn’t be allowed to vote, and holding other dehumanising views. imo, that is very relevant background: it tells me that whatever this person thinks that others should do is completely irrelevant.

                                                                                  1. 4

                                                                                    yes you are entitled to your opinion, so is the author else we could not have a dialog about these subjects. The view in the piece is “fix your bugs” and “fuzz your bugs” and “be responsible” not “don’t write bugs”.

                                                                                    And Rust is about “preempt a class of bugs” well so is any language that consider nulls a design flaw for instance. So are languages that prevent side effects, that enforce exhaustive conditionals, that enforce exception handling, and so on. So it isn’t the ultimate language.

                                                                                    1. 2

                                                                                      “don’t write bugs” doesn’t work despite 40 years of industry experience with unsafe languages.

                                                                                      Except in cryptography. In this particular niche, “don’t write bug” is both mandatory and possible. In this particular niche, Rust is of very little help.

                                                                                      That said, the author may not be aware of the specifics of cryptography. He may be right for the wrong reasons.

                                                                                    2. 13

                                                                                      I think “consistently being wrong” is a valuable insight, and can span unrelated subjects.

                                                                                      1. 5

                                                                                        “You should not break other people’s operating systems” is not a wrong thing to say.

                                                                                        Very reasonable, but not what’s happening, nor what he’s saying.

                                                                                        What’s happening is “making a change to one software project”, that is provided under a license that does not guarantee support.

                                                                                        What he’s saying is “changing what platforms you support is unacceptable”. He’s also saying “switching to Rust is a dereliction of duty”. Which implies “you have a duty that is not listed in your software license, and which I won’t elaborate on”.

                                                                                        In other words, what he’s saying is, ultimately, “nobody should make changes to their software that I disapprove of”. Which is wildly unreasonable.

                                                                                        Unsurprisingly, his political views skew towards “the only people who are allowed to be part of society are people that I approve of” (he approves only of a certain subset of Christian faithful, who must also be straight and cisgendered, believe that certain parts of the Constitution are invalid, and be in the top fraction of earners).

                                                                                        In other words, his poor political thinking mirrors his thinking on the politics of open source development in ways that make it relevant to the conversation.

                                                                                        1. 2

                                                                                          What’s happening is “making a change to one software project”, that is provided under a license that does not guarantee support.

                                                                                          What’s happening is “making a breaking change” without marking it as such (deprecation, major version number bump, that kind of thing). That’s not okay. I don’t care it was a labour of love provided for free. The rules should be:

                                                                                          1. Don’t. Break. Users. Pretty please.
                                                                                          2. If you break rule (1), bump the major version number.
                                                                                          3. If rule (1) was broken, keep the old versions around for a while. Bonus point if you can actually support them (fix bugs etc).
                                                                                          1. 5

                                                                                            It’s not a breaking change if it breaks on platforms that were never explicitly supported (not even by python). (I’m not entirely sure if they used to support these explicitly, but it’s not obvious).

                                                                                            1. 2

                                                                                              I agree if there’s an explicit description of supported platforms. If not… the only reasonable fallback would be any platform supported by Python where it builds & run out of the box. That can mean a lot of platforms.

                                                                                            2. 2

                                                                                              If you break rule (1), bump the major version number

                                                                                              They did, at least for certain values of “major version number”. Rust was introduced in 3.4. The x.y releases are when backwards-incompatible changes are introduced. They’re changing their versioning scheme to make it more explicity: next major version will be 35 (instead of 3.5).

                                                                                              Honestly, a quick look at their changelog shows backwards-incompatible changes at 3.3, 3.1, 3.0, 2.9, … In other words, adding rust when they did was entirely in line with their release cycle.

                                                                                              1. 1

                                                                                                I commend them for listening to feedback (or is it cave in to mass anger?), and switch to semantic versioning. That’s cogent evidence of trustworthiness in my book.

                                                                                        2. 2

                                                                                          Author here.

                                                                                          Everyone is full of crud on some level. However, interacting with people nicely on the Internet is a good way for me to get rid of that and to become less of a terrible person.

                                                                                          On that note, hi! I’m Gavin. Nice to meet you. :)

                                                                                        1. 2

                                                                                          I wrote a raspberry pi router with a custom made captive portal, firewall rules to customize, tag and log traffic per user, and sign those logs using openssl. Ruby/Sinatra/Sequel/SQLite backend, JQuery/Bootstrap/Websocket frontend. I still go back to it from time to time to remember how to handle iptables, local dns, openssl, sinatra, sequel, etc.

                                                                                          1. 10

                                                                                            First they ignore you, then they ridicule you, then they make clumsy imitations of your features while claiming they came up with them.

                                                                                            1. 14

                                                                                              I don’t think they’ll ever again miss the point so spectacularly as when they added Option tho.

                                                                                              1. 4

                                                                                                Same question as I have for the parent: for someone not following what happens in Java and hasn’t come across any articles about this: what’s wrong with Java’s Option?

                                                                                                1. 9

                                                                                                  My interpretation: Option is what you use when you have non-nullable references, but you want a Nothing value. But in Java, all references are nullable per default, so what does the Option provide? Now you have two Null values: null and Nothing. Ok, then you use NonNull<Option<A>> in concert with your IDE. But that is clumsy.

                                                                                                  The proper solution would probably involve a new binding syntax, which would be non-nullable by default.

                                                                                                  1. 6

                                                                                                    The solution would be to add a type specifier or operator which creates explicitly non-nullable types and support that at language level because we can’t go back in time to make non-nullable a language default.

                                                                                                    1. 7

                                                                                                      I think C# is making good progress in that regard. Expect a badly copied version of that in Java 34, I guess.

                                                                                                    2. 5

                                                                                                      People always bring this up in discussions about Optional, it’s not a problem in practice. I’ve never seen someone try to return null on a method that returns an Optional and if I did it wouldn’t pass code review.

                                                                                                      The proper solution, which is planned, is to change it to a “primitive object” that has no identity and cannot be null. This seems to be coming relatively soon considering Valhalla has been in the works for a while and this JEP popped up recently.

                                                                                                      1. 3

                                                                                                        primitive object

                                                                                                        I wonder what will be the final name of this.

                                                                                                        has no identity

                                                                                                        I always found this Java-self-invented lingo pretty weird – if it’s possible to ask “is this identical to that”, it has identity. I think Java devs mixing up “same reference” with “identical” caused this confusion.

                                                                                                        1. 2

                                                                                                          Primitive object seems to be the final name, they started with value objects, moved to inline object, and then settled on primitive object. I’m not a huge fan of it but there was some rationalization on the mailing lists.

                                                                                                          I always found this Java-self-invented lingo pretty weird – if it’s possible to ask “is this identical to that”, it has identity. I think Java devs mixing up “same reference” with “identical” caused this confusion.

                                                                                                          This isn’t unique to Java, C# and Python use identity in the same fashion: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/objects#object-identity-vs-value-equality https://docs.python.org/3/reference/expressions.html#is-not

                                                                                                          1. 1

                                                                                                            I guess it’s no coincidence that all those languages have problems with identity/equality around floating points.

                                                                                                            (Which is not about floating points in particular, but they serve as a nice canary to indicate that their approach to equality/identity is broken.)

                                                                                                    3. 5

                                                                                                      Multiple methods are implemented incorrectly and violate monad laws, causing weird behavior around null. But that is “works as intended”, because Java is “pragmatic”.

                                                                                                      A minor nitpick is that Optional is not marked Serializable, making everyone’s life a bit more miserable than it had to be. (The explanation they gave for that was bullshit for various reasons.)

                                                                                                      1. 3

                                                                                                        I believe they forgot to make Optional be iterable, which breaks a lot of the properties it has in other languages.

                                                                                                        1. 4

                                                                                                          You can use Optional.stream(), which you can iterate.

                                                                                                    4. 1

                                                                                                      For those not following along, what are the issues with Java records?

                                                                                                    1. 3

                                                                                                      My question for SQLite users is how do you handle migrations affecting existing tables? I remember starting a project with it and creating a migration with an ALTER TABLE for an existing column and running into issues. I looked at the docs and it said you have to create a new table, copy everything from the old one, and then rename the new table, which is a major PITA. At that point I just switched to local postgres.

                                                                                                      1. 4

                                                                                                        This is a non-trivial operation in most production databases I’ve worked with. Schema mutation usually requires a synchronized deployment of new application code, with the attendant downtime/read-only lock while that push catches up. You also have to wait for your RDBMS to finish the arbitrarily long, multi-stage DML run(s) while you rewrite indices, change defaults/null-handling, or convert values, then verify that the conversion worked before you open up the write path again.

                                                                                                        SQLite makes some things much harder or impossible (primarily multi-host access to one consistent database) but IME schema migrations aren’t a much bigger deal than they are for client/server DBs.

                                                                                                        1. 5

                                                                                                          It sounds like you’ve had much more experience with RDBMS’s than I have and I don’t deny what you’re saying is true, it’s just a bit besides the point I was making. When I use Postgres and want to alter a table, I just write a migration and tell flyaway to run it. It may have to handle stuff under the hood and take a long time, but for me it has “just worked” likely due to the DB size. With SQLite I would have to write all this sql to copy rename existing stuff to do the same thing, it’s more of an ergonomic problem.

                                                                                                          1. 3

                                                                                                            That’s a totally reasonable point; sorry if I jumped straight to “production trauma” stories. :)

                                                                                                            If you remember from that previous project, I am curious which types of schema mutation limitations you’ve encountered? There are some limitations to the SQLite in-place ALTER options, but not that many given that you can’t e.g. add a new non-NULL column in most DBs without providing another default, violate existing foreign key constraints, etc.

                                                                                                            https://www.sqlite.org/lang_altertable.html

                                                                                                            (Not trying to play dumb to force a “gotcha” moment. I’m genuinely curious since as you noted, I’ve mostly worked with “big” databases like PostgreSQL and SQL Server in recent memory.)

                                                                                                            1. 2

                                                                                                              AFAIR SQLite doesn’t support column alter or drop operations which means you would need to create a new table, copy the data over, drop the old table and rename the new one.

                                                                                                              1. 1

                                                                                                                @rcoder I’m pretty sure this was it. I think I was on an early iteration of a project and wanted to drop a column but was unable to.

                                                                                                        2. 3

                                                                                                          You just never drop a column, and whenever have need, alter the old column name to deprecated and add a new column. That is at least how people do this with SqlDelight.

                                                                                                          Or you bite the bullet and do the data moves in one transaction, with some obvious downsides (double the size of the table, and need to call vacuum afterwards). This is how Core Data does it.

                                                                                                          I have other solutions to this in my SQLite ORM :) https://github.com/liuliu/dflat#schema-evolution

                                                                                                          1. 1
                                                                                                            ALTER TABLE foo RENAME TO _foo;
                                                                                                            CREATE TABLE foo (a INTEGER NOT NULL, b INTEGER DEFAULT 0);
                                                                                                            INSERT INTO foo (a) SELECT a FROM _foo;
                                                                                                            DROP TABLE _foo;
                                                                                                            
                                                                                                            1. 1

                                                                                                              Yes, which is rather verbose for the

                                                                                                                alter table foo add column b integer default 0
                                                                                                              

                                                                                                              (or similar) that many other systems support.

                                                                                                              1. 2

                                                                                                                SQLite supports ALTER TABLE ADD COLUMN. It just doesn’t support removing columns. (Changing a column’s type is moot because SQLite mostly ignores column types; it uses dynamic types per row.)

                                                                                                                1. 1

                                                                                                                  yes sure, but SQLite does not support many ALTER commands, this is a generic way of modifying tables that works for everything.