Waaah, I don't get paid to use new shiny languages


  • Considered Harmful

    @HardwareGeek said in Waaah, I don't get paid to use new shiny languages:

    @hungrier Not all JS errors are run-time errors. Many of them are design-time errors.

    Such as the error of choosing JS?

    Meh, you can compile down to asm.js, which is a super simple subset of JS, that doesn't really have errors per se.



  • @Mason_Wheeler said in Waaah, I don't get paid to use new shiny languages:

    :wtf_owl: Any even remotely competent message pump will have a system that keeps track of messages that have been processed, and if a given message fails to process more than X number of times, it shunts it off into an "errored messages" jail for developers to take a look at and then proceeds with the next message.

    This isn't a message queue in the traditional IBM "this is important transactional state that a batch process will eventually get around to committing" sense. It was intended to allow UI events to "cut in line" in front of synthetic events and deferrals, and allow a Web page to keep "working" despite e.g. some FrontPage rollover button abomination passing out on the floor. That it's now being used for handling critical business transactions in Node is an unintended side effect of where Node came from.


  • Trolleybus Mechanic

    @hungrier said in Waaah, I don't get paid to use new shiny languages:

    I've been reading it bit by bit over the past few days and just got to this part:

    Elm is a functional compile-to-js language used primarily for frontend web development.

    What makes Elm unique is its promise of no runtime exceptions, ever. Applications written in Elm are very robust.

    That's a bold claim, when compiling to a language comprised entirely of runtime errors

    I saw a dev give a presentation on elm at a small local conference a couple years ago. It was clear from the presentation that she had never used another language besides Javascript before. Every example of a great thing about elm (which were legit good things) was presented as if the concepts were new to her. It was an interesting and also odd presentation.



  • @hungrier said in Waaah, I don't get paid to use new shiny languages:

    I've been reading it bit by bit over the past few days and just got to this part:

    Elm is a functional compile-to-js language used primarily for frontend web development.

    What makes Elm unique is its promise of no runtime exceptions, ever. Applications written in Elm are very robust.

    That's a bold claim, when compiling to a language comprised entirely of runtime errors

    From what very, very little I know about Elm, you end up doing a lot of null-checks as you go, before stuffing data into very-strict types. And then, with those very-strict types, you can do all sorts of processing, because anything that might possibly be null will have that baked into the type, and the compiler will throw fits if you do anything strong with a nullable type without checking for null.

    I suppose it might be a bit like TypeScript's strict mode in that way, but with the added joy of forcing you to verify all of the JSON you get from APIs.

    Still won't save you from out-of-memory errors, of course. And it wouldn't surprise me if index-out-of-range and other run-time errors on dynamic data were still quite possible. But it's supposed to be waaaaaaay stricter than JS, and still stricter than TS.


  • Banned

    @PotatoEngineer said in Waaah, I don't get paid to use new shiny languages:

    But it's supposed to be waaaaaaay stricter than JS

    Not a very high bar.

    and still stricter than TS.

    Better, but nothing to brag about either.

    And as always, they've achieved the seemingly impossible goal by changing definitions of words. No runtime exceptions, ever. By runtime exceptions we mean only these few specific ones, not all of them. And by ever, we only mean these specific parts of code, not the entire runtime of the application.


  • :belt_onion:

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    db is null? Well, the world is already fucked, so any attempt at handling that is gonna be useless.

    You still don't get it. It's not about whether db is null right now or not. It's about db being guaranteed to never be null under any circumstances.

    No, you don't get it.
    The same thing that would cause db to be null would likely be a fatal error in a language that didn't allow nulls. Unless you're routinely assigning null to critical variables, in which case you're being stupid.

    You won't just accidentally get a null out of nowhere.


  • Banned

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    The same thing that would cause db to be null would likely be a fatal error in a language that didn't allow nulls.

    Yes, exactly. A fatal error that prevents compilation. You have to guarantee that no such fatal error could ever occur or it won't even compile.

    You won't just accidentally get a null out of nowhere.

    You absolutely can. And as decades of programming history shows us, it's way more common than we'd like to admit. Mostly due to programming errors. Static type systems exist to detect programming errors before the code can even be run. And the more advanced the type system is - the more constraints can be explicitly encoded in type signatures, the better.

    Maybe db is a bit overdramatic. But function arguments being null on accident happens all the time. Having a formal guarantee that an argument will never be null is an ENORMOUS improvement. Even just a dynamic check is great, because then you can catch it early and it won't mess other stuff, and the stack trace makes sense. But static check is even better. The mere fact that you have a compiled program you can deploy is by itself an indisputable proof that this situation will never happen. Not just never happen unless something so inconceivable happens that it doesn't even make sense to recover anymore. It will never happen, period.


  • :belt_onion:

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    Yes, exactly. A fatal error that prevents compilation. You have to guarantee that no such fatal error could ever occur or it won't even compile.

    OMG!

    Wait, Rust can prevent my database from ever becoming disconnected at runtime?

    THAT'S AMAZING.

    I'm switching now!

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    But function arguments being null on accident happens all the time.

    I genuinely cannot remember encountering this. Sure, you might have a variable that's being passed in that can be nonexistent, but that's rather the point of null, now isn't it?


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Wait, Rust can prevent my database from ever becoming disconnected at runtime?

    Show me a language where non-null db connection suddenly becomes null when connection is lost. Or, in other words, stop with the red herring.

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    I genuinely cannot remember encountering this. Sure, you might have a variable that's being passed in that can be nonexistent, but that's rather the point of null, now isn't it?

    The problem of null is not that it exists at all, but that it exists in its current form, where it cannot be excluded as a valid value at compile time. If something is optional, if should be explicitly optional.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    Show me a language where non-null db connection suddenly becomes null when connection is lost. Or, in other words, stop with the red herring.

    That's about the only possible reason I can think of for a global db variable becoming null. Remember, this is his example, not mine. Given the context, db is presumably initialized once, at application startup, and not assigned again. If you can think of a reason it would become null during runtime, please elaborate. Perhaps it is a red herring, but I legitimately can't think of a circumstance where it would become null, so I'm thinking outside the box here (maybe the database connection... changes the assignment to null because it went away? idk? It is both Javascript and NodeBB so anything is possible)


  • area_pol

    @sloosecannon it that case I think you misunderstood the example. If a language has explicit means of expressing the lack of value, there's no possibility to pass a null-ish value without a build error. In other words, you can only check for null at run time in Java, but mistakenly passing a None value would result in a compile-time error in Rust.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon it that case I think you misunderstood the example. If a language has explicit means of expressing the lack of value, there's no possibility to pass a null-ish value without a build error. In other words, you can only check for null at run time in Java, but mistakenly passing a None value would result in a compile-time error in Rust.

    The original example was this:

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    @izzion you've specifically chosen the exceptional example, something you encounter once every few thousand lines of code, where you ACTUALLY EXPECT a null to appear. This isn't what regular code looks like. Regular code looks like this (copied from a random file in NodeBB repo, because I couldn't think of a better example):

        async function (uid, roomId, newName) {
    		if (!newName) {
    			throw new Error('[[error:invalid-name]]');
    		}
    		newName = newName.trim();
    		if (newName.length > 75) {
    			throw new Error('[[error:chat-room-name-too-long]]');
    		}
    
    		const payload = await plugins.hooks.fire('filter:chat.renameRoom', {
    			uid: uid,
    			roomId: roomId,
    			newName: newName,
    		});
    		const isOwner = await Messaging.isRoomOwner(payload.uid, payload.roomId);
    		if (!isOwner) {
    			throw new Error('[[error:no-privileges]]');
    		}
    
    		await db.setObjectField('chat:room:' + payload.roomId, 'roomName', payload.newName);
    		await Messaging.addSystemMessage('room-rename, ' + payload.newName.replace(',', ','), payload.uid, payload.roomId);
    
    		plugins.hooks.fire('action:chat.renameRoom', {
    			roomId: payload.roomId,
    			newName: payload.newName,
    		});
    	};
    
    • This function never checks whether uid is null. Everything will violently blow up if it ever is.
    • This function never checks whether roomId is null. Everything will violently blow up if it ever is.
    • This function never checks whether the result of trim call is null. Everything will violently blow up if it ever is.
    • This function does check whether newName.length is null, but only by accident, and returns very misleading error message when it is.
    • This function never checks whether plugins, plugins.hooks or plugins.hooks.fire is null. Everything will violently blow up if it ever is.
    • This function never checks whether payload, payload.uid, payload.roomId or payload.newName is null. Everything will violently blow up if it ever is.
    • This function never checks whether Messaging, Messaging.isRoomOwner or Messaging.addSystemMessage is null. Everything will violently blow up if it ever is.
    • This function never checks whether db or db.setObjectField is null. Everything will violently blow up if it ever is.
    • This function never checks whether the result of replace call is null. Everything will violently blow up if it ever is.
    • Two potentially null values are passed to plugins.hooks.fire function in each call. If it ever actually happens to be null, it will take up to a few days to even tell where those nulls are coming from in the first place.
    • Two more potentially null values are passed to Messaging.isRoomOwner.
    • One more potentially null value is passed to db.setObjectField.

    You could argue none of this matter because you know these things will never be null, but do you really? The point of option types is to guarantee that yes, really, these things will never ever ever ever ever be null, it's just completely impossible. I can't imagine why you would ever NOT want that - for what's promised to be impossible to be actually impossible.

    The way I'm understanding what he's saying is that there's a problem here, because you have to check to see if any one of that long list of variables is null. What I'm trying to say is that in the real world, you don't have to check for that anyways because it's effectively impossible for them to be null anyways (and if they are, you have bigger problems).

    Effectively, there are only a few things in there that could feasibly ever be null, and of those few, I'd argue most of them should be able to be null anyways - as a valid value representing an invalid result.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    The way I'm understanding what he's saying is that there's a problem here, because you have to check to see if any one of that long list of variables is null. What I'm trying to say is that in the real world, you don't have to check for that anyways because it's effectively impossible for them to be null anyways (and if they are, you have bigger problems).

    And he is absolutely right - you assume the caller of the function will respect its contract, but you don't have any means to enforce it. That's the typical run-time nullability problem (and the "billion dollar mistake"). Some languages can enforce it by their type systems, therefore you don't need to assume anything - it's impossible to pass empty values.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    The way I'm understanding what he's saying is that there's a problem here, because you have to check to see if any one of that long list of variables is null. What I'm trying to say is that in the real world, you don't have to check for that anyways because it's effectively impossible for them to be null anyways (and if they are, you have bigger problems).

    And he is absolutely right - you assume the caller of the function will respect its contract, but you don't have any means to enforce it. That's the typical run-time nullability problem (and the "billion dollar mistake"). Some languages can enforce it by their type systems, therefore you don't need to assume anything - it's impossible to pass empty values.

    Sure, and part of why things like uid and roomId can be null is because of Javascript being weird.

    But at the same time, assuming that, since they're "IDs", they're numeric, what's preventing the caller from passing in an invalid number? How does enforcing that it can't be one invalid value help when you have to check to see if the value is actually valid in context anyways?(especially since, once again excluding Javascript type coercion weirdness, you can probably check if it's null and if it's a valid value in context at the same time)


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Sure, and part of why things like uid and roomId can be null is because of Javascript being weird.

    That's the problem with all languages having implicit empty values like null.

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    But at the same time, assuming that, since they're "IDs", they're numeric, what's preventing the caller from passing in an invalid number?

    Nothing - that's a problem with dynamically types languages.

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    How does enforcing that it can't be one invalid value help when you have to check to see if the value is actually valid in context anyways?

    That's limiting the number of potential bugs. With strong type systems you can require the value to be both present and be a number. That's a pretty strong contract to begin with. But checking if it has logical sense in a given runtime context is another thing entirely.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    Nothing - that's a problem with dynamically types languages.

    Not really - if this was statically typed it would still be just as easy to pass in -1 or 8 (chosen from a perfectly random dice roll), or 2147483647.

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    That's limiting the number of potential bugs.

    But what bug, exactly, could happen here? If you're operating on data you're being given without checking that it's valid first, that's a bug waiting to happen anyways. And if you're checking if it's valid, the null check comes free!


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    That's the problem with all languages having implicit empty values like null.

    Also, important note that since this is Javascript, the implicit empty value is in fact not null and is actually undefined, which means if you run into a null that's a pretty clear sign that someone wrote code intending to make that variable null somewhere.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Not really - if this was statically typed it would still be just as easy to pass in -1 or 8 (chosen from a perfectly random dice roll), or 2147483647.

    By invalid number I assumed you meant e.g. a string.

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    But what bug, exactly, could happen here?

    Passing anything that is not a number. A typical bug with using an invalid type with dynamically typed languages. That's why strongly typed ones are safer in this regard.

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    If you're operating on data you're being given without checking that it's valid first, that's a bug waiting to happen anyways. And if you're checking if it's valid, the null check comes free!

    Your making some incorrect assumptions here. First, you assume passing a value which is not valid in a given context is a bug. If a function contract is "give me ANY numeric id and I'll check if it's ok and return an error otherwise", passing a logically incorrect value is not a bug. On the other hand, passing e.g. a date object would be a bug, because you're breaking the contract and a compiler might allow it. Again, that's why strongly typed languages prevent such classes of bugs.

    Second assumption is assuming we're talking about primitives. We can imagine an example function calling foo() on an input object an expecting it to be of a given interface. If there's no restriction on that interface, someone can freely pass anything which has a foo() method, thus potentially introducing bugs. What's more, someone might even pass a null, which was the starting problem.

    In the end, I see I'm teaching someone the differences between strongly and weekly typed languages, which is pointless, given the amount of resources on that subject. Go look it up yourself.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    The way I'm understanding what he's saying is that there's a problem here, because you have to check to see if any one of that long list of variables is null. What I'm trying to say is that in the real world, you don't have to check for that anyways because it's effectively impossible for them to be null anyways (and if they are, you have bigger problems).

    And he is absolutely right - you assume the caller of the function will respect its contract, but you don't have any means to enforce it. That's the typical run-time nullability problem (and the "billion dollar mistake"). Some languages can enforce it by their type systems, therefore you don't need to assume anything - it's impossible to pass empty values.

    Re-reading this, I think you're talking about me assuming that it's effectively impossible to be null?

    This function never checks whether the result of trim call is null. Everything will violently blow up if it ever is.

    Trim is a built-in method with a guarantee. It does not return null.

    This function does check whether newName.length is null, but only by accident, and returns very misleading error message when it is.

    .length is a built-in method to all strings with a specific guarantee. It does not return null.

    This function never checks whether plugins, plugins.hooks or plugins.hooks.fire is null. Everything will violently blow up if it ever is.

    These are part of the NodeBB internal API that many things rely on. If they are null, your program has fallen apart and there's nothing you can do about it.

    This function never checks whether payload, payload.uid, payload.roomId or payload.newName is null. Everything will violently blow up if it ever is.

    This... is probably a fair argument. But it's probably valid, in context, for payload to be null, to represent an invalid response.

    This function never checks whether Messaging, Messaging.isRoomOwner or Messaging.addSystemMessage is null. Everything will violently blow up if it ever is.

    These are part of the NodeBB internal API that many things rely on. If they are null, your program has fallen apart and there's nothing you can do about it.

    This function never checks whether db or db.setObjectField is null. Everything will violently blow up if it ever is.

    These are part of the NodeBB internal API that many things rely on. If they are null, your program has fallen apart and there's nothing you can do about it.

    This function never checks whether the result of replace call is null. Everything will violently blow up if it ever is.

    .replace is a built-in method to all strings with a specific guarantee. It does not return null.

    Two potentially null values are passed to plugins.hooks.fire function in each call. If it ever actually happens to be null, it will take up to a few days to even tell where those nulls are coming from in the first place.

    Yes, they should be checked. But you should also probably check to see if they're valid uids and roomIDs too. Null checks here are irrelevant.

    Two more potentially null values are passed to Messaging.isRoomOwner.

    Considering this method's purpose is to validate something (check if uid owns roomID), it makes sense that it would handle invalid inputs (including nulls)

    One more potentially null value is passed to db.setObjectField.

    No, considering that Messaging.isRoomOwner would return false if passed invalid data...


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    In the end, I see I'm teaching someone the differences between strongly and weekly typed languages, which is pointless, given the amount of resources on that subject. Go look it up yourself.

    I don't need to be taught the differences between strongly and weakly[sic] typed languages. I'm well aware. I have programmed in both. You seem to be making the argument against weak typing - IE Javascript, not against null?

    What about strongly typed languages that allow null values, such as Java or C#?


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    What about strongly typed languages that allow null values, such as Java or C#?

    That's the billion dollar mistake.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    What about strongly typed languages that allow null values, such as Java or C#?

    That's the billion dollar mistake.

    No, it's the billion dollar un-mistake!

    Really though, I fail to see how it's a mistake. We've debated/made the point on how Javascript is bad because weak typing, but nothing you've said has succeeded in pivoting that, in my mind, to strongly typed languages that allow for null


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    but nothing you've said has succeeded in pivoting that, in my mind, to strongly typed languages that allow for null

    Instead of me copy-pasting, you can google it for yourself, starting with that quote, which comes from the person who invented null in the first place.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    but nothing you've said has succeeded in pivoting that, in my mind, to strongly typed languages that allow for null

    Instead of me copy-pasting, you can google it for yourself, starting with that quote, which comes from the person who invented null in the first place.

    Right, I'm aware of the quote and I also disagree with the over-generalized argument, which is "All null references are bad". null represents data that you don't have, or data that is invalid. Unfortunately, because we live in a world that's not perfect, you will have invalid data. There needs to be a way to represent that very real-world data in programs, or your program won't be able to handle the real world.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, I'm aware of the quote and I also disagree with the over-generalized argument, which is "All null references are bad"

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    The problem of null is not that it exists at all, but that it exists in its current form, where it cannot be excluded as a valid value at compile time. If something is optional, if should be explicitly optional.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, I'm aware of the quote and I also disagree with the over-generalized argument, which is "All null references are bad"

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    The problem of null is not that it exists at all, but that it exists in its current form, where it cannot be excluded as a valid value at compile time. If something is optional, if should be explicitly optional.

    And I disagree with that, because, in my experience, you'll just end up making everything optional anyways. Very few things are guaranteed never to have an invalid value.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    And I disagree with that, because, in my experience, you'll just end up making everything optional anyways.

    Then you have some painful experiences. I'm in this industry ~20y and I'm yet to see such approach, thankfully.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    And I disagree with that, because, in my experience, you'll just end up making everything optional anyways.

    Then you have some painful experiences. I'm in this industry ~20y and I'm yet to see such approach, thankfully.

    so, OK.

    In this theoretical utopia of non-nullness, how do you handle, for example, a Customer that doesn't have a Birthday set? Do you have to make the Birthday an Optional<Date>? What about one that hasn't set their MiddleName? Or First or Last name, for that matter.


  • Discourse touched me in a no-no place

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Very few things are guaranteed never to have an invalid value.

    Actually the inverse is true, but typically the guarantee is made by virtue of the fact that the particular piece of code would be unreachable if the data was invalid, or originates from code that provably never produces an invalid value.


  • :belt_onion:

    @dkf said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Very few things are guaranteed never to have an invalid value.

    Actually the inverse is true, but typically the guarantee is made by virtue of the fact that the particular piece of code would be unreachable if the data was invalid, or originates from code that provably never produces an invalid value.

    Thank you for putting that more eloquently than me. I've been up late...


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    In this theoretical utopia of non-nullness, how do you handle, for example, a Customer that doesn't have a Birthday set? Do you have to make the Birthday an Optional<Date>?

    That theoretical utopia is called Rust: https://doc.rust-lang.org/std/option/


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    In this theoretical utopia of non-nullness, how do you handle, for example, a Customer that doesn't have a Birthday set? Do you have to make the Birthday an Optional<Date>?

    That theoretical utopia is called Rust: https://doc.rust-lang.org/std/option/

    Right, so instead of null checks populating your code, you have Optional checks populating your code?


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, so instead of null checks populating your code, you have Optional checks populating your code?

    Yes, and that means you cannot pass an empty value, where it's not explicitly expected, therefore avoiding accidentally passing them. You also cannot get the actual value back without checking for it's existence, therefore avoiding accidentally accessing empty values. You also get means to expressively show if something is required or not, on the language level, therefore avoiding unnecessary checks. If you make a mistake, the code won't build, rather than exploding at runtime.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, so instead of null checks populating your code, you have Optional checks populating your code?

    Yes, and that means you cannot pass an empty value, where it's not explicitly expected, therefore avoiding accidentally passing them. You also cannot get the actual value back without checking for it's existence, therefore avoiding accidentally accessing empty values. You also get means to expressively show if something is required or not, on the language level, therefore avoiding unnecessary checks. If you make a mistake, the code won't build, rather than exploding at runtime.

    Maybe I'm crazy, but I really don't see any reason for this to exist. It's just as complex to write (maybe even a little more?) and provides very little benefit, based off of everything I've done. In terms of issues I've actually encountered, null problems are like... 0.001% of them.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Maybe I'm crazy, but I really don't see any reason for this to exist. It's just as complex to write (maybe even a little more?) and provides very little benefit, based off of everything I've done. In terms of issues I've actually encountered, null problems are like... 0.001% of them.

    Therefore I can only encourage you to try to use it and you'll see the difference both in quality and productivity.


  • :belt_onion:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Maybe I'm crazy, but I really don't see any reason for this to exist. It's just as complex to write (maybe even a little more?) and provides very little benefit, based off of everything I've done. In terms of issues I've actually encountered, null problems are like... 0.001% of them.

    Therefore I can only encourage you to try to use it and you'll see the difference both in quality and productivity.

    To be clear, I'm not saying I don't see a reason for Rust to exist. That's a whole other can of worms and if it does do what it's supposed to, that's a good thing. It's a little too low-level for my taste though. I just see no need for enforced no-nullness across a language.


  • area_pol

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    I just see no need for enforced no-nullness across a language.

    Ok, but you also need to realize that's a subjective feeling - if you don't see a need for something, it doesn't mean there is no need.


  • ♿ (Parody)

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    I just see no need for enforced no-nullness across a language.

    Ok, but you also need to realize that's a subjective feeling - if you don't see a need for something, it doesn't mean there is no need.


  • Discourse touched me in a no-no place

    @boomzilla said in Waaah, I don't get paid to use new shiny languages:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    I just see no need for enforced no-nullness across a language.

    Ok, but you also need to realize that's a subjective feeling - if you don't see a need for something, it doesn't mean there is no need.

    I'm looking forward to when they reinvent checked exceptions. Their structured error types are almost there, except for the need to explicitly handle things everywhere…


  • Banned

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    Yes, exactly. A fatal error that prevents compilation. You have to guarantee that no such fatal error could ever occur or it won't even compile.

    OMG!

    Wait, Rust can prevent my database from ever becoming disconnected at runtime?

    Are you doing this on purpose or do you just not understand what null is?

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    But function arguments being null on accident happens all the time.

    I genuinely cannot remember encountering this.

    This statement is equivalent to "never have I ever been surprised to see a null reference exception". I just don't believe you.



  • @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, so instead of null checks populating your code, you have Optional checks populating your code?

    Yes, and that means you cannot pass an empty value, where it's not explicitly expected, therefore avoiding accidentally passing them. You also cannot get the actual value back without checking for it's existence, therefore avoiding accidentally accessing empty values. You also get means to expressively show if something is required or not, on the language level, therefore avoiding unnecessary checks. If you make a mistake, the code won't build, rather than exploding at runtime.

    All of that sounds a lot like null checks with extra steps. Instead of checking if (client.birthDate != null) everywhere, you would have the pattern matching equivalent (whatever the syntax) Optional(birthDate): do_the_thing(); None: don't()


  • area_pol

    @hungrier you're missing the point(s) here. It's not that you don't have checks - you do. The point is that empty values are explicit, not implied. The point is that you cannot pass one by mistake. The point is that you cannot use a possibly-empty/null value by mistake. If you try, the code will not compile, rather than explode at runtime.


  • ♿ (Parody)

    @hungrier said in Waaah, I don't get paid to use new shiny languages:

    @NeighborhoodButcher said in Waaah, I don't get paid to use new shiny languages:

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    Right, so instead of null checks populating your code, you have Optional checks populating your code?

    Yes, and that means you cannot pass an empty value, where it's not explicitly expected, therefore avoiding accidentally passing them. You also cannot get the actual value back without checking for it's existence, therefore avoiding accidentally accessing empty values. You also get means to expressively show if something is required or not, on the language level, therefore avoiding unnecessary checks. If you make a mistake, the code won't build, rather than exploding at runtime.

    All of that sounds a lot like null checks with extra steps. Instead of checking if (client.birthDate != null) everywhere, you would have the pattern matching equivalent (whatever the syntax) Optional(birthDate): do_the_thing(); None: don't()

    The point is that you couldn't omit the check. So shit still happens, but you are less likely to mishandle it. Not that you couldn't still have the equivalent of ON ERROR RESUME.



  • @NeighborhoodButcher I hadn't been following the conversation too closely, just remembered seeing a similar thing in the article and what I thought of it at the time. But thinking about it more now, I can see at least one advantage, that everything downstream has a guaranteed non-null value.


  • Considered Harmful

    @Gąska said in Waaah, I don't get paid to use new shiny languages:

    Maybe db is a bit overdramatic. But function arguments being null on accident happens all the time. Having a formal guarantee that an argument will never be null is an ENORMOUS improvement. Even just a dynamic check is great, because then you can catch it early and it won't mess other stuff, and the stack trace makes sense. But static check is even better. The mere fact that you have a compiled program you can deploy is by itself an indisputable proof that this situation will never happen. Not just never happen unless something so inconceivable happens that it doesn't even make sense to recover anymore. It will never happen, period.

    I've seen more than one third-party program crash with the error "pure virtual function call." As I understand it (and I don't use C++ any more), that means that somewhere, a method got called on an abstract class that wasn't defined. As far as I know, the language semantics are never supposed to allow this to happen; and yet, it happens. There are no hard guarantees.


  • Considered Harmful

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    .length is a built-in method to all strings with a specific guarantee. It does not return null.

    I actually agree with you, but I'm going to :um-pendant: you because there's all kinds of fun things you can tamper with like prototypes and own properties to invalidate this contract.

    You'd be crazy to do it, but... You could slap a length property on a string or array, or even replace String.prototype.length or Array.prototype.length, not to mention you could trick the duck typing by passing an object that is merely Array**-like** that doesn't conform to the same contract. Oh, and object Proxies are a thing.


  • Considered Harmful

    @sloosecannon said in Waaah, I don't get paid to use new shiny languages:

    weakly[sic]

    :um-pendant: again (I guess I'm in that mood)....

    https://www.grammarbook.com/blog/definitions/sic/ said:

    Sic is a Latin term meaning “thus.” It is used to indicate that something incorrectly written is intentionally being left as it was in the original. Sic is usually italicized and always surrounded by brackets to indicate that it was not part of the original. Place [sic] right after the error.

    Only use [sic] if you retained the error, not if you corrected it.



  • @error said in Waaah, I don't get paid to use new shiny languages:

    an object that is merely Array‌-like that doesn't conform to the same contract

    You'd have to be doing something really crazy, like trying to use the result of .querySelectorAll


  • Considered Harmful

    @dkf said in Waaah, I don't get paid to use new shiny languages:

    originates from code that provably never produces an invalid value.

    In a world where everything else honors its contracts 100% and never changes them, this is true. I don't live in that world.

    Invalid data can come from anywhere - user input, database values, web services, modules from npm written by 13 year olds... Your chain of trust in data integrity is as strong as the weakest link in that chain.


  • Considered Harmful

    @error said in Waaah, I don't get paid to use new shiny languages:

    @dkf said in Waaah, I don't get paid to use new shiny languages:

    originates from code that provably never produces an invalid value.

    In a world where everything else honors its contracts 100% and never changes them, this is true. I don't live in that world.

    Invalid data can come from anywhere - user input, database values, web services, modules from npm written by 13 year olds... Your chain of trust in data integrity is as strong as the weakest link in that chain.

    I think as a web developer I'm used to receiving "dirty" values because I'm always taking data from somewhere else and passing it on. It's helped me to develop a healthy paranoia about verifying data at every step...
    With that said, it's exactly the reason I prefer dynamically typed languages. The data I work with can and does take all shapes and forms, and actually defining every possible variation would take me more code and more time than writing the domain logic itself.


Log in to reply