|
Hammerite posted:NB. I am aware that the above doesn't take account of fallthrough/goto-case, but a switch statement using these is equivalent to the if-else version if you add gotos in the appropriate places.
|
# ? Jul 4, 2015 00:41 |
|
|
# ? May 27, 2024 04:02 |
|
b0lt posted:Literally everything PHP does is a bad choice Yup.
|
# ? Jul 4, 2015 05:00 |
|
JawnV6 posted:I think restricting the comparison to == is more limiting than literal values. This is reasonable. I see functional languages' pattern-matching feature praised a lot (mostly by people who really like functional languages, but still). But I haven't used hardcore functional languages so I don't really have experience enough to like/dislike it. One could imagine a sort of "generalised switch" statement that takes two arguments, a comparison function and an operand. The basic switch statement being the generalised one in the case where the comparison function is a test for equality. In the case of PHP specifically the usefulness of its switch statement must I imagine be impacted by the fact it uses == and not === b0lt posted:Literally everything PHP does that differs from the mainstream is a bad choice The "arbitrary expressions in case labels in a switch statement" behaviour and the "continue is meaningful in a switch statement" behaviour are both in my view good choices, for reasons I have explained in previous posts. If you would argue that either is a bad choice because it will surprise people who are used to the way other languages do things, then that's a reasonable position to hold, but in order to be consistent you need to apply the same pessimism to any decision made by any other language that goes against the grain. If on the other hand you're just posting to bash PHP because PHP is in general terrible, that's fine too, but I see no reason to regard the rare good idea that PHP throws out (maybe by accident or in a "stopped clock is right twice a day" fashion) as "poisoned" just because it's associated with PHP. That's not the way reasonable people evaluate ideas.
|
# ? Jul 4, 2015 10:57 |
|
Hammerite posted:The "arbitrary expressions in case labels in a switch statement" behaviour and the "continue is meaningful in a switch statement" behaviour are both in my view good choices, for reasons I have explained in previous posts. If you would argue that either is a bad choice because it will surprise people who are used to the way other languages do things, then that's a reasonable position to hold, but in order to be consistent you need to apply the same pessimism to any decision made by any other language that goes against the grain. The reason I'm not a big fan of switch statements with conditionals is that semantically, the switch operator is meaningless if you're providing a list of expressions for cases. To demonstrate, here is how to get a switch statement to work in javascript using expressions.... quote:// switch on amount Why bother?
|
# ? Jul 4, 2015 16:12 |
|
Hammerite posted:One could imagine a sort of "generalised switch" statement that takes two arguments, a comparison function and an operand. The basic switch statement being the generalised one in the case where the comparison function is a test for equality. F# does (basically) this and it's pretty great
|
# ? Jul 4, 2015 18:11 |
|
Pattern matching is the best, yeah
gonadic io fucked around with this message at 22:15 on Jul 4, 2015 |
# ? Jul 4, 2015 22:03 |
|
Hammerite posted:One could imagine a sort of "generalised switch" statement that takes two arguments, a comparison function and an operand. So basically condp.
|
# ? Jul 5, 2015 07:27 |
|
match thing with | Some x -> x | None -> ()
|
# ? Jul 5, 2015 08:10 |
|
Captain Capacitor posted:match thing with Seriously gently caress every language designer who has ever included null after this was invented
|
# ? Jul 5, 2015 08:39 |
|
Soricidus posted:Seriously gently caress every language designer who has ever included null after this was invented I'm possibly missing some subtlety above, but null is useful in imperative based programming languages where you don't know what the value of a variable to be assigned will be yet, and it doesn't have a sensible default value. It also fulfills the useful requirement of failing hard and fast when one arises unexpectedly - it means you've got a logic error or a failure to respect the interface of a method call. I think most .NET programmers wouldn't mind as much if the null reference exception just listed the variable name somehow (or if the runtime was able to infer the type the object was meant to be). e: I guess you're encoding that it can return a unit in the signature of the method, which could be useful - but isn't unit in danger of becoming a bucket type like null then? i.e. It's undefined, or the method does something under the covers. Milotic fucked around with this message at 10:27 on Jul 5, 2015 |
# ? Jul 5, 2015 10:23 |
|
PHP just doesn't go far enough IMO.https://en.wikipedia.org/wiki/Guarded_Command_Language posted:The selection (often called the "conditional statement" or "if statement") is a list of guarded commands, of which one is chosen to execute. If more than one guard is true, one statement is nondeterministically chosen to be executed. If none of the guards are true, the result is undefined.
|
# ? Jul 5, 2015 10:39 |
|
Milotic posted:I'm possibly missing some subtlety above, but null is useful in imperative based programming languages where you don't know what the value of a variable to be assigned will be yet, and it doesn't have a sensible default value. quote:It also fulfills the useful requirement of failing hard and fast when one arises unexpectedly - it means you've got a logic error or a failure to respect the interface of a method call. I think most .NET programmers wouldn't mind as much if the null reference exception just listed the variable name somehow (or if the runtime was able to infer the type the object was meant to be). quote:e: I guess you're encoding that it can return a unit in the signature of the method, which could be useful - but isn't unit in danger of becoming a bucket type like null then? i.e. It's undefined, or the method does something under the covers. If it's encoded in the signature of the method and I have to unwrap it explicitly (like returning a Maybe or an Either) then it's obvious from the caller side that I have to handle both cases. When null is allowed by default it is terrible because every method that returns an object could be returning null. Maybe this one returns null on error! Maybe it throws an exception! We just don't know. Eric Lippert has said that he wishes .NET had non-nullable references by default. But now it's too late. Null is not a good idea. The "problems" it "solves" either don't really exist or have much better solutions.
|
# ? Jul 5, 2015 10:39 |
|
The point is that "a variable that may or may not have been assigned any useful value" is a bad thing and a regular source of bugs, and having null as a regular value means literally any variable can be in that state without warning. Option types in languages without null mean that the default is for it to be safe to assume that a variable has a value, and in the cases where there's a good reason for that not to be the case, that's explicitly stated in such a way that trivial static analysis can detect whether the code is going to handle that case. Algebraic data types and pattern matching mean that things like option types can be handled relatively nicely. Contrast the hideous syntax in Java's half-assed implementation.
|
# ? Jul 5, 2015 10:41 |
|
Dessert Rose posted:Not initializing the variable is a perfectly acceptable option here. Your compiler should be able to work out if the variable is definitively initialized before use in all execution paths. Within a method yes, but some times you really do need to return a null. e.g. A method that returns information on something in the real world - what's the address of this person. Oh it's not been added yet. quote:Wouldn't it be better if the compiler could catch that you weren't respecting the interface of a method call? Yes, but it would likely not cover every edge case and possibly bloat compile times. quote:If it's encoded in the signature of the method and I have to unwrap it explicitly (like returning a Maybe or an Either) then it's obvious from the caller side that I have to handle both cases. I definitely agree that returning a Maybe or Either forces you to handle it, but that can cause issues as well: 1) You use a 'railway orientated' approach and it ends up bubbling to the top anyway. Depending on the language, you have difficulty tracking it back to the place where it wrong. This is especially a problem in deeply nested systems. I've done something like this in systems built in C# which should avoid throwing exceptions, so they return an Attempt<T> object instead, and sometimes you do wish you had a stack trace at the point it first went wrong. 2) It forces you to make a decision there and then about what to do in order to get the program to compile, which you might not be able to make at the time. Or you might make the wrong one. Some systems benefit from crashing hard and fast when they run into edge cases like this. I have to admit, of all the problems with C# (it's a great language but the .NET framework is bit wonky in places especially 1.0 apis), I don't personally rate null reference exceptions as that big of a problem. It's highly likely my experience has been coloured by the types of problems I've had to work on though. I've done a lot of work on build, test and monitoring systems in secure environments, so everything is terrible in a different way. It would be interesting to see what falls out in terms of quirks and painpoints when you do start having ADTs and pattern matching in languages meant for LOB apps, where stuff is often a bit woolly, and you get edge cases for certain customers, accounts, geographic regions, time zones, whatever. (This is my chief concern with functional programming in particular - if you're trading 40 stock exchanges, they all differ in weird ways and at different points. Sometimes you just need to hack stuff). I'd be quite happy with null staying in the language, but with language support for code contracts. Though even then that can lead to fun and games with polymorphism - inputs valid for one implementation aren't for another, but they all use the same interface since interfaces being injected in can be more descriptive than a general function call. (Func is great, but abused it can be as meaningless as Tuple<X,Y> vs a properly named class).
|
# ? Jul 5, 2015 11:49 |
|
quote:1) You use a 'railway orientated' approach and it ends up bubbling to the top anyway. Depending on the language, you have difficulty tracking it back to the place where it wrong. This is especially a problem in deeply nested systems. I've done something like this in systems built in C# which should avoid throwing exceptions, so they return an Attempt<T> object instead, and sometimes you do wish you had a stack trace at the point it first went wrong. You want to log or message the point where it went wrong anyway. In your example, if your FetchAddress() method finds that the address hasn't been added yet, you're going to want to show the user something like "Address not found!", and maybe also write in a log file some more specific information such as which particular query failed. Also, if you've seen the same Railway Oriented Programming slides I have, then you know that you can just return a custom error type and know at the end of the railway where it is exactly that the failure happened, without need for exceptions or stack traces. NihilCredo fucked around with this message at 12:25 on Jul 5, 2015 |
# ? Jul 5, 2015 12:23 |
|
Not having null is great, but if this compiles...Captain Capacitor posted:match thing with ... then your unit type is basically just null anyway (or x is () too).
|
# ? Jul 5, 2015 12:39 |
|
Milotic posted:Within a method yes, but some times you really do need to return a null. e.g. A method that returns information on something in the real world - what's the address of this person. Oh it's not been added yet. Milotic posted:1) You use a 'railway orientated' approach and it ends up bubbling to the top anyway. Depending on the language, you have difficulty tracking it back to the place where it wrong. This is especially a problem in deeply nested systems. If you also need to avoid exceptions, then you already have a problem and null doesn't help. Milotic posted:2) It forces you to make a decision there and then about what to do in order to get the program to compile, which you might not be able to make at the time. Or you might make the wrong one. Some systems benefit from crashing hard and fast when they run into edge cases like this.
|
# ? Jul 5, 2015 12:46 |
|
Milotic posted:Within a method yes, but some times you really do need to return a null. e.g. A method that returns information on something in the real world - what's the address of this person. Oh it's not been added yet. Milotic posted:I definitely agree that returning a Maybe or Either forces you to handle it, but that can cause issues as well: You need to do one of these with nullable types too, it's just that option types force you to be explicit about how you are handling it. (and if the best way of handling it is to fail with a stack trace immediately, you can do that!) Because nulls don't force you to be explicit about how they're handled, it's very easy to have the error show up in a weird place - maybe your null reference gets passed around for a while and it's only when a method actually ends up getting called on it that you get your stack trace. e: Okay I got beaten pretty badly there. What Soricidus said. Jeb Bush 2012 fucked around with this message at 12:56 on Jul 5, 2015 |
# ? Jul 5, 2015 12:51 |
|
Vanadium posted:Not having null is great, but if this compiles... Option.None is conceptually much the same as null, yes. But the big difference is that every other method in the program can take a Some x as argument and the compiler will automatically guarantee that it won't be fed nulls, ever. Whereas with nulls, you can never tell apart a variable that has been null-checked from one that hasn't, so you're forced to always null-check all your arguments anyway.
|
# ? Jul 5, 2015 16:17 |
|
I'm talking about unit/(), not None here.
|
# ? Jul 5, 2015 16:39 |
|
The whole point of the Option type is to make it so the compiler can require that you deal with a possibly missing value in a safe way. Once you get used to it, null will put a very sour taste in your mouth.
|
# ? Jul 5, 2015 17:00 |
|
Vanadium posted:I'm talking about unit/(), not None here. Ah, sorry. Yeah, that's a pretty poor pattern matching block; you're supposed to return the same type for every case, so either you return a x on both sides (i.e. for the None case you return a default value for x) or you return a unit on both sides (i.e. for the Some case, you do something with x and return unit). Returning a type that can be either unit or x is indeed just pushing the null-check downstream.
|
# ? Jul 5, 2015 17:00 |
|
Milotic posted:Yes, but it would likely not cover every edge case and possibly bloat compile times. As to the latter: compile times are like the last thing I care about, compared to getting a crash report from production because of a nullref. I'll happily blow an hour a day on automated tools that tell me when I could be loving up. Isn't the entire point of a managed language to help you not blow your foot off? That's what we're spending all those runtime resources on, right? If you don't want compiler warnings for every possible mistake in your code, why not just write native code? As to the former: The point is not to cover every edge case, necessarily, but to make it very difficult to make this kind of mistake. It may be possible to "trick" the compiler one way or the other (usually managed compilers err on the side of, well, errors, if they can't figure things out) but that is a sign that you are doing something wrong too. If a machine can't figure out your code's intent, you should probably restructure it.
|
# ? Jul 5, 2015 17:25 |
|
Milotic posted:2) It forces you to make a decision there and then about what to do in order to get the program to compile, which you might not be able to make at the time. Or you might make the wrong one. Some systems benefit from crashing hard and fast when they run into edge cases like this. It doesn't really, and that's the point. Your method can simply return an Option as well, passing the lack-of-data error (which may or may not actually be an error, but let's assume it is for now) along to the caller. The difference is with an Option the caller of your method is explicitly told that it should expect the possibility of no returned value rather than you just knowing to handle the possible exception from the docs. If you really want your method to take a Class1 and return a Class2 rather than an Option of each, the caller can always lift your method to handle that case. That is what map is for after all.
|
# ? Jul 5, 2015 21:38 |
|
KernelSlanders posted:It doesn't really, and that's the point. Your method can simply return an Option as well, passing the lack-of-data error (which may or may not actually be an error, but let's assume it is for now) along to the caller. The difference is with an Option the caller of your method is explicitly told that it should expect the possibility of no returned value rather than you just knowing to handle the possible exception from the docs. If you really want your method to take a Class1 and return a Class2 rather than an Option of each, the caller can always lift your method to handle that case. That is what map is for after all. Passing back to the caller the lack of data (and exposing that possibility in your interface explicitly with the type system) *is* deciding what to do in that case. Edit: I'm in agreement with you, to be clear.
|
# ? Jul 5, 2015 22:09 |
|
NihilCredo posted:You want to log or message the point where it went wrong anyway. In your example, if your FetchAddress() method finds that the address hasn't been added yet, you're going to want to show the user something like "Address not found!", and maybe also write in a log file some more specific information such as which particular query failed. or just return a NoAddress() object.
|
# ? Jul 6, 2015 07:36 |
|
null is seriously the most overrated "problem" ever. If you just pretend they don't exist, that a pointer in null state is just a trap representation that you can never read or compare to anything, i.e. that the nullness of a pointer is something you know statically, then you won't get any big costly problems in your software development (and certainly some non-nullable reference type being the default would be worse).
|
# ? Jul 6, 2015 07:43 |
|
sarehu posted:null is seriously the most overrated "problem" ever. If you just pretend they don't exist, that a pointer in null state is just a trap representation that you can never read or compare to anything, i.e. that the nullness of a pointer is something you know statically, then you won't get any big costly problems in your software development (and certainly some non-nullable reference type being the default would be worse).
|
# ? Jul 6, 2015 12:09 |
|
|
# ? Jul 6, 2015 12:22 |
|
I dunno, if the volume of posts about null is anything to go by, null is the most serious problem since...Y2K!
|
# ? Jul 6, 2015 17:53 |
|
Thermopyle posted:I dunno, if the volume of posts about null is anything to go by, null is the most serious problem since...Y2K! I know you snark, but Y2K was legitimately a huge problem.
|
# ? Jul 6, 2015 17:58 |
|
Doctor w-rw-rw- posted:I know you snark, but Y2K was legitimately a huge problem. Well, whatever.
|
# ? Jul 6, 2015 18:02 |
|
It's a pretty good comparison, because programmers expend tons of effort to ensure that the enormous mistake from the past doesn't actually cause that much damage.
|
# ? Jul 6, 2015 18:57 |
|
Volte posted:What happens when the libraries you call don't pretend that The answer is, unsurprisingly, you have to read libraries' API documentation.
|
# ? Jul 6, 2015 19:46 |
|
Doctor w-rw-rw- posted:I know you snark, but Y2K was legitimately a huge problem. Yeah and all the tigers would've been a huge problem too if it weren't for my rock!
|
# ? Jul 6, 2015 19:51 |
|
"This so-called 'problem' isn't a problem because you can just bolt your own conceptual constraints on top of the language and rely, never making any mistakes, on the comprehensive, accurate documentation for any libraries you use."
|
# ? Jul 6, 2015 20:20 |
|
sarehu posted:The answer is, unsurprisingly, you have to read libraries' API documentation. Now one of the libraries used by one of the libraries used by one of the libraries you use has changed in such a way that a method that used never to return null can now return null. One of the intermediate libraries does not share your passion for being incredibly careful and never making a single mistake. By some miracle all the library tests still pass (the miracle is that the library has tests at all), so nobody notices that the documentation of the library you are actually relying on is now incorrect. But now your code is getting unexpected NPEs. This situation is literally impossible in a language where nullability is explicit, with basically no discernible downside except for occasionally maybe having to let your IDE type a few more characters for you.
|
# ? Jul 6, 2015 20:35 |
|
http://www.diogonunes.com/blog/custom-build-configurations-visualstudio/ How not to use build configurations with Visual Studio I mean, yeah that's how you set them up. But it's not what they're for. code:
|
# ? Jul 6, 2015 20:54 |
|
No Safe Word posted:http://www.diogonunes.com/blog/custom-build-configurations-visualstudio/ I did this once to change the constructor of a class. Not only the meat of it, but depending on the setting it also changed what arguments it took.
|
# ? Jul 6, 2015 21:10 |
|
|
# ? May 27, 2024 04:02 |
|
No Safe Word posted:http://www.diogonunes.com/blog/custom-build-configurations-visualstudio/ What a strange way to approach that particular problem. I mean I guess it's a little more automated... but huh. I wouldn't even think of that.
|
# ? Jul 6, 2015 21:12 |