I don't find prototypes to offer anything over open classes myself.
For me, it's about pedagogy. Classes (in the context of statically-typed languages) define strong interfaces between components. However, that's antithetical to the dynamically-typed nature of Python and Ruby. In those languages, objects are simple dictionaries and the class construct gives some (slight) convenience for initially populating those dictionaries. I don't like conflating the two concepts (class-as-interface, class-as-convenience) together. The one thing I appreciate about Javascript is that it embraces its dynamic-typedness and does not go down this route.
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
Apothe0sisHave you ever questioned the nature of your reality?Registered Userregular
Version control - can anyone recommend a quickstart guide? Specifically one that goes over the theory and conventions? Like "you should commit under these scenarios. Here's what the buzzwords mean" and that sort of thing.
you should commit under the scenario that you did something you want to save, for starters
then, upon attaining mastery, start committing individual pieces of functionality
small commits help me a lot in large system debugging because when something fucked up happened, I can look at the last 24 hour of commits and see exactly what has changed in an otherwise stable system to cause bugs... in addition to normal debugging routines
I try to commit what I have when I leave for the day if and ONLY if it doesn't break the build. I try to live under the idea that I could be hit by a bus on the way home.
you should commit under the scenario that you did something you want to save, for starters
then, upon attaining mastery, start committing individual pieces of functionality
small commits help me a lot in large system debugging because when something fucked up happened, I can look at the last 24 hour of commits and see exactly what has changed in an otherwise stable system to cause bugs... in addition to normal debugging routines
That is the best part. Then rolling back if you need to.
not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
I try to commit what I have when I leave for the day if and ONLY if it doesn't break the build. I try to live under the idea that I could be hit by a bus on the way home.
I live under the premise that this is not my problem, and that if a programmer can't figure it out, welp, sucks to be them.
not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
@Apothe0sis, what version control system do you currently use?
Because, after having used GIT for the past 2 years, I would jump ship back to Subversion in a heartbeat. http://www.thegeekstuff.com/2011/04/svn-command-examples/
I try to commit at least once a day.
For major changes, this means splitting up my work into smaller chunks, where sometimes those small chunks aren't even referenced, so I can safely commit it, without breaking the build or unit tests.
I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.
For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
+3
gavindelThe reason all your softwareis brokenRegistered Userregular
Commits? Oh, yes, commits.
For the first month I worked here, I thought the depot saved things automatically. Nope.
For the next month, I thought I was successfully syncing with the depot, but was actually saving to the local depot file on my machine.
Tomorrow is my last day, so I think I'm going to convert my project to one giant notepad file and email it to my project manager.
Angels, innovations, and the hubris of tiny things: my book now free on Royal Road! Seraphim
I want to do something in Python that seems like it should be a solved problem what with the itertools library
I have two lists:
a = [A,B,C,D]
b = [1,2]
I want the output to be (in the case of these lists)
(A,1),(A,2),(B,1),(B,2),(C,1),(C,2),(D,1),(D,2)
but b could sometimes be the empty list and in those cases the output should be
(A,None),(B,None),(C,None),(D,None)
I started trying something with zip_longest but that was a non starter. Obviously I can write this code myself but it feels like something the should just be a couple of nested function calls.
I want to do something in Python that seems like it should be a solved problem what with the itertools library
I have two lists:
a = [A,B,C,D]
b = [1,2]
I want the output to be (in the case of these lists)
(A,1),(A,2),(B,1),(B,2),(C,1),(C,2),(D,1),(D,2)
but b could sometimes be the empty list and in those cases the output should be
(A,None),(B,None),(C,None),(D,None)
I started trying something with zip_longest but that was a non starter. Obviously I can write this code myself but it feels like something the should just be a couple of nested function calls.
Work colleague points out this could be made lovlier with a simple
product(a, b or [None])
Such elegance, much terseness, wow
Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
I've been tasked with creating a thing that will download some records in the DB as either a csv or txt file. The records, however, could change in a couple different ways over time (column values change, more records added, that sort of thing). So, I'm wondering if it's possible to create something that can run through the records and create the necessary file in memory, then have it download to the client without me actually having to save a hard copy of these files on the web server. I guess that might be considered a file stream, or something? I don't usually work with files, so I'm a bit clueless in that regard.
I'm using PHP :rotate: like always, so I'm not sure if it has the capabilities to do what I want.
PSN/XBL/Nintendo/Origin/Steam: Nightslyr 3DS: 1607-1682-2948 Switch: SW-3515-0057-3813 FF XIV: Q'vehn Tia
I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.
For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
I used to commit this way, but after working on larger projects, I found that this way leads to integration problems, and thus, more work on your side.
In larger projects, multiple people end up working on the same code base, sometimes interfering with each other. The best way to deal with this is to commit often, daily or at minimum, every other day, to force more frequently, smaller merges.
You end up doing less work overall, if your commits are earlier, since your merge difference will be smaller. Plus it gives you the advantage over people who like to merge late, or with big changes, as they have to merge their code with yours, not the other way around, which puts the effort on them, rather than on you.
Manager: "Hey urahonky, do you think you can get chart colors working by Friday?"
Me: "Yeah now that the service auto-deploys and it's up on the environment it shouldn't be a problem."
Guess what is broken? Auto-deployments. Guess how much work I have been able to finish on the colors today?
Are there are any good studies of language performance in the C++/C#/Java realm that look at usage of std:: in C++ versus "raw" C/C++ usage?
My basic question, does liberal use of std:: negate the performance benefits of C++ over C# and Java?
In short no, but from the research that we've conducted (bringing efficient memory safety to C++), using std:: does not impact runtime performance versus comparable use of standard libraries in other languages. The performance delta in C++ versus Java that we observed was from memory locality and cache-friendliness, in particular, abuse of heap allocations.
EDIT: as a concrete example, if you go full std:: and, e.g., use std::vector with std::iterator to walk over the list, the performance footprint after template expansion and subsequent optimization is literally pointer-over-array as you would expect. In contrast with Java, the iterator object constitutes a heap-allocated object that you must explicitly walk through in order to access the underlying array.
Kambing on
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
I commit for each issue, with the relevant tracking numbers, so that anyone with the number can see exactly what I did to address the specific issue. Handy when it crops up elsewhere and someone is reading past defects on how it was fixed.
For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
I used to commit this way, but after working on larger projects, I found that this way leads to integration problems, and thus, more work on your side.
In larger projects, multiple people end up working on the same code base, sometimes interfering with each other. The best way to deal with this is to commit often, daily or at minimum, every other day, to force more frequently, smaller merges.
You end up doing less work overall, if your commits are earlier, since your merge difference will be smaller. Plus it gives you the advantage over people who like to merge late, or with big changes, as they have to merge their code with yours, not the other way around, which puts the effort on them, rather than on you.
That's what I'm talking about, versus arbitrary "commit end of day errrr week?" type stuff some people do.
Our commits are feature/fix based and that's almost always easier to integrate than a whole dump of unrelated changes that are only tied together because the same person did them that week.
Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
I don't have a problem with it myself, 'or' returns a value that will evaluate to True or False (if it looks like a duck and quacks like a duck...).
I wonder if it would be valid C to use the ternary operator to do the same thing...
Rollers are red, chargers are blue....omae wa mou shindeiru
i only do the once daily commit on things I don't care about or are unlikely to be rolled back or conflict ever
anything remotely sensitive i will do atomic commits, or nearly-atomic commits.... not tied to any specific ticket number, but just functionally related
Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
I don't have a problem with it myself, 'or' returns a value that will evaluate to True or False (if it looks like a duck and quacks like a duck...).
I wonder if it would be valid C to use the ternary operator to do the same thing...
The types don't line up. 'or' takes two things that are (convertible to a) bool and produces a bool. In Python, 'or' takes two things that are (convertible to a bool) and produces a value that is convertible to a bool. More precisely, the type is:
Boolable a, Boolable b => a -> b -> a | b
Where a | b is the union type because the type of the result of `or` depends on which of the operands is selected. C/C++ doesn't allow this directly because a | b is not a valid type in the language, although you can use unions to achieve the same effect.
EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
>>> x = []
>>> y = []
>>> z = x and y # Hrm, what is z referring to?
>>> x.append(1)
>>> y.append(2)
>>> z
[1]
The definition of `or` in Python is consistent but not what I would call sensible. Similarly to this in Javascript:
Which is also consistent given the ECMAscript standard, but not sensible by any stretch of the imagination. Dynamically-typed languages typically sacrifice being sensible for flexibility, and I typically treasure the former over the latter.
Kambing on
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
The standard style when using 'or' and 'and' with Boolable values is that one of them will be a constant whilst the other is a variable which avoids the confusion over what value will be returned by the expression.
I make a little face when the boolean or comparison operator is used on values which are not explicitly boolean. That is not what the boolean comparison operator is for, and it's simply confusing!
This is ESPECIALLY true in languages like C++ when you are comparing values which are intended to be numbers, and you use the boolean value of the int as true or false. I would much rather see:
if(a != 0)
than...
if(a)
It's an ease of readability issue. If your thing has only two values, and they are obviously mapped to true/false 1/0, then boolean is right for the situation. People use it all the time because it's less space, but seriously? Screen space is NOT at a premium, and trading even a couple lines of code for readability (especially since most compilers will optimize the extra lines out anyway) is nearly always a HUGE win.
The standard style when using 'or' and 'and' with Boolable values is that one of them will be a (non-Falsey) constant whilst the other is a variable.
Yup. The standard use is reasonable. However, I prefer that the language act reasonably with both standard and non-standard usage, because you can't anticipate which situation the programmer will find themselves in. And this is especially true in a dynamically-typed language where frequently errors are raised far (both spatially and temporally) from where the actual error occurred.
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
>>> x = []
>>> y = []
>>> z = x and y # Hrm, what is z referring to?
>>> x.append(1)
>>> y.append(2)
>>> z
[1]
The definition of `or` in Python is consistent but not what I would call sensible.
I don't think that is weird, but I also already knew that 'and' and 'or' are short-circuit operators in Python. 'z' couldn't have been 'y' since the latter was never evaluated. In the case of 'or' then 'y' would've been chosen.
In practice, the only place I make use of 'or' like that is initializing variables. Due to how Python treats mutable default arguments (they are created when the function is defined, not called) you'll see this pattern used:
def foo(a, b=None):
b = b or []
If you used "b=[]" in the argument list, the state of 'b' would persist across all invocations of 'foo'.
Rollers are red, chargers are blue....omae wa mou shindeiru
Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
But it's not a question of fine print. As an Ada programmer should I get annoyed that every other language uses short-circuit logical operators rather than having to make it explicit with 'or else'/'and then' like nature intended? No, I should learn the way of doing things in other langauges otherwise we're all stuck programming to the lowest common denominator of expressibility and that means we're all stuck writing Algol60.
if 5 < x < 10:
#Do thing
Causes most other languages to crash on compilation, should it be verbotten to use that in Python as it would confuse those unfamiliar?
Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
You don't need to know exactly how it is implemented. It's described here in a truth table with short notes.
Rollers are red, chargers are blue....omae wa mou shindeiru
EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
>>> x = []
>>> y = []
>>> z = x and y # Hrm, what is z referring to?
>>> x.append(1)
>>> y.append(2)
>>> z
[1]
The definition of `or` in Python is consistent but not what I would call sensible.
I don't think that is weird, but I also already knew that 'and' and 'or' are short-circuit operators in Python. 'z' couldn't have been 'y' since the latter was never evaluated. In the case of 'or' then 'y' would've been chosen.
In practice, the only place I make use of 'or' like that is initializing variables. Due to how Python treats mutable default arguments (they are created when the function is defined, not called) you'll see this pattern used:
def foo(a, b=None):
b = b or []
If you used "b=[]" in the argument list, the state of 'b' would persist across all invocations of 'foo'.
It isn't the fact that `or` in Python is short-circuiting --- in most languages && and || are short-circuiting operators. It's the fact that, in Python, `or` (and `and`) produce non-boolean values which is very non-standard, especially from a types perspective as I pointed out above. The reason why that's the case is to have convenient syntax for "defaulting" values like what you described above. However, rather than lumping that into a non-standard definition of `or`, I'd rather see that be placed into some other operator (or function).
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
Writing your code in a way that you have to understand Python is very Pythonic!
But yeah, I always just try to figure out a language I am working with. There are always things that you should know and what you should expect to see.
Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
You don't need to know exactly how it is implemented. It's described here in a truth table with short notes.
Eh. That is how it is implemented. That's exactly the piece of the documentation you have to find to answer Rend's question: oh wait, `or` produces a non-boolean value? What value does it produce then?.
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
+1
gavindelThe reason all your softwareis brokenRegistered Userregular
Got an offer. Such salary, much benefit package, wow.
Angels, innovations, and the hubris of tiny things: my book now free on Royal Road! Seraphim
Got an offer. Such salary, much benefit package, wow.
Make sure you graduate, instead of accepting a job that requires you to drop out.
+5
GnomeTankWhat the what?Portland, OregonRegistered Userregular
Essentially Python's 'or' acts as both an OR and a coalescing operator, and it's on my list of reasons I hate Python. It's low on the list mind you, but it's on the list.
Also just to add, I should not need to go look up the fine print about how precisely an or statement is implemented in the language in order to make sense of a line of code: knowing what or means in general should be enough. The line "product(a, b or [None])" requires just that of me.
But it's not a question of fine print. As an Ada programmer should I get annoyed that every other language uses short-circuit logical operators rather than having to make it explicit with 'or else'/'and then' like nature intended? No, I should learn the way of doing things in other langauges otherwise we're all stuck programming to the lowest common denominator of expressibility and that means we're all stuck writing Algol60.
if 5 < x < 10:
#Do thing
Causes most other languages to crash on compilation, should it be verbotten to use that in Python as it would confuse those unfamiliar?
No. Of course, when in Rome, do what the Romans do. But certainly, just becomes the Romans do something in their home, it isn't an ideal thing to do.
Python, in particular, favors convenience over regularity in its semantics. I personally don't like that about the language from both a designer's perspective --- irregularity leads to hard-to-diagnose errors --- and an educator's perspective --- irregularity means more "corners" that a student needs to reason about.
Comparison chaining is one of those conveniences (albeit less offensive because it's more difficult to produce "poisonous" errors from them). In most languages, comparisons are a binary operator so 5 < x < 10 is ill-typed because precedence dictates that we have (5 < x) < 10 and (5 < x) has type bool and 10 is type int which are incomparable things.
In Python, comparisons are not strictly binary. Indeed you can have chains of them, e.g.,
>>> x = 3
>>> y = 7
>>> 0 <= x <= y <= 10
True
Which is very convenient because this is how we'd normally write comparisons. But because of regularity of syntax, we can also write expressions such as:
>>> 0 <= y >= x <= 10
True
>>> 0 <= y >= x <= 3
True
Which does not obey our common sense understanding of how comparison chaining works, at least when we write such things on paper --- y = 7 which is not <= 3 so surely the expression is False. By trial-and-error or reading the standard (https://docs.python.org/2/reference/expressions.html#not-in), you can derive what is actually happening:
e1 op1 e2 op2 ... opn em
~equivalent to~
(e1 op1 e2) and (e2 op2 e3) and ... (em-1 opn em)
Which explains why y <= 3 is not checked. To do "the thing you might expect" requires more mathematical smarts (systems-of-constraints solving) than a compiler writer is willing to invest. And so we reach a compromise in language design regularity versus "convenience" where many languages opt for the former (regularity) and Python opts for the latter (convenience). "Convenience" is in quotes because while such semantics enable some common case comparison chaining, they are not general enough to handle all of the cases that the language admits (in the way that you expect, at least).
(EDIT: there's also the whole bit about side-effects in the language as well. Note that it seems like the desugared form of a comparison chain requires that we evaluate each of e2 ... em-1 twice. If these expressions contained side-effects, then those side-effects would be evaluated twice. Thankfully, the Python standard notes that each expression is explicitly only evaluated once in the usual short-circuiting fashion even though the expanded form suggests otherwise.)
Kambing on
@TwitchTV, @Youtube: master-level zerg ladder/customs, commentary, and random miscellany.
Posts
He's got the new hardware ready for programming and I haven't even begun on the bootloader yet to configure our DDR controller.
So, this is how our game is to be played, eh? Efficiently!
I'm watching you, hardware guy.
Now imagining that you work in Konami's arcade hardware division. Shhh, it's OK, don't disillusion me.
I made a game, it has penguins in it. It's pay what you like on Gumroad.
Currently Ebaying Nothing at all but I might do in the future.
then, upon attaining mastery, start committing individual pieces of functionality
small commits help me a lot in large system debugging because when something fucked up happened, I can look at the last 24 hour of commits and see exactly what has changed in an otherwise stable system to cause bugs... in addition to normal debugging routines
That is the best part. Then rolling back if you need to.
but the record of line changes is useful
I live under the premise that this is not my problem, and that if a programmer can't figure it out, welp, sucks to be them.
Because, after having used GIT for the past 2 years, I would jump ship back to Subversion in a heartbeat.
http://www.thegeekstuff.com/2011/04/svn-command-examples/
I try to commit at least once a day.
For major changes, this means splitting up my work into smaller chunks, where sometimes those small chunks aren't even referenced, so I can safely commit it, without breaking the build or unit tests.
For new projects or features, I commit once I am happy with my own testing. After that every change is a request/fix with a tracking number and we do the above.
For the first month I worked here, I thought the depot saved things automatically. Nope.
For the next month, I thought I was successfully syncing with the depot, but was actually saving to the local depot file on my machine.
Tomorrow is my last day, so I think I'm going to convert my project to one giant notepad file and email it to my project manager.
Work colleague points out this could be made lovlier with a simple
Such elegance, much terseness, wow
I made a game, it has penguins in it. It's pay what you like on Gumroad.
Currently Ebaying Nothing at all but I might do in the future.
Ugh. I find that code rather gross. But that stems from the weirdness involving `or` producing non-boolean values in order to facilitate (insignificant) syntactic conveniences like this.
My basic question, does liberal use of std:: negate the performance benefits of C++ over C# and Java?
I've been tasked with creating a thing that will download some records in the DB as either a csv or txt file. The records, however, could change in a couple different ways over time (column values change, more records added, that sort of thing). So, I'm wondering if it's possible to create something that can run through the records and create the necessary file in memory, then have it download to the client without me actually having to save a hard copy of these files on the web server. I guess that might be considered a file stream, or something? I don't usually work with files, so I'm a bit clueless in that regard.
I'm using PHP :rotate: like always, so I'm not sure if it has the capabilities to do what I want.
Switch: SW-3515-0057-3813 FF XIV: Q'vehn Tia
In larger projects, multiple people end up working on the same code base, sometimes interfering with each other. The best way to deal with this is to commit often, daily or at minimum, every other day, to force more frequently, smaller merges.
You end up doing less work overall, if your commits are earlier, since your merge difference will be smaller. Plus it gives you the advantage over people who like to merge late, or with big changes, as they have to merge their code with yours, not the other way around, which puts the effort on them, rather than on you.
Manager: "Hey urahonky, do you think you can get chart colors working by Friday?"
Me: "Yeah now that the service auto-deploys and it's up on the environment it shouldn't be a problem."
Guess what is broken? Auto-deployments. Guess how much work I have been able to finish on the colors today?
0%.
In short no, but from the research that we've conducted (bringing efficient memory safety to C++), using std:: does not impact runtime performance versus comparable use of standard libraries in other languages. The performance delta in C++ versus Java that we observed was from memory locality and cache-friendliness, in particular, abuse of heap allocations.
EDIT: as a concrete example, if you go full std:: and, e.g., use std::vector with std::iterator to walk over the list, the performance footprint after template expansion and subsequent optimization is literally pointer-over-array as you would expect. In contrast with Java, the iterator object constitutes a heap-allocated object that you must explicitly walk through in order to access the underlying array.
That's what I'm talking about, versus arbitrary "commit end of day errrr week?" type stuff some people do.
Our commits are feature/fix based and that's almost always easier to integrate than a whole dump of unrelated changes that are only tied together because the same person did them that week.
I wonder if it would be valid C to use the ternary operator to do the same thing...
anything remotely sensitive i will do atomic commits, or nearly-atomic commits.... not tied to any specific ticket number, but just functionally related
The types don't line up. 'or' takes two things that are (convertible to a) bool and produces a bool. In Python, 'or' takes two things that are (convertible to a bool) and produces a value that is convertible to a bool. More precisely, the type is:
Where a | b is the union type because the type of the result of `or` depends on which of the operands is selected. C/C++ doesn't allow this directly because a | b is not a valid type in the language, although you can use unions to achieve the same effect.
EDIT: related, when both operands are false, then `or` is defined to not return False but b instead. This sort of makes sense for `or`, but by symmetry, `and` returns the a value by default. Then you get weird situations like this:
The definition of `or` in Python is consistent but not what I would call sensible. Similarly to this in Javascript:
> [] + {} "[object Object]" > {} + [] 0 > {} + {} NaN > [] + [] ""Which is also consistent given the ECMAscript standard, but not sensible by any stretch of the imagination. Dynamically-typed languages typically sacrifice being sensible for flexibility, and I typically treasure the former over the latter.
I made a game, it has penguins in it. It's pay what you like on Gumroad.
Currently Ebaying Nothing at all but I might do in the future.
This is ESPECIALLY true in languages like C++ when you are comparing values which are intended to be numbers, and you use the boolean value of the int as true or false. I would much rather see:
than...
It's an ease of readability issue. If your thing has only two values, and they are obviously mapped to true/false 1/0, then boolean is right for the situation. People use it all the time because it's less space, but seriously? Screen space is NOT at a premium, and trading even a couple lines of code for readability (especially since most compilers will optimize the extra lines out anyway) is nearly always a HUGE win.
Yup. The standard use is reasonable. However, I prefer that the language act reasonably with both standard and non-standard usage, because you can't anticipate which situation the programmer will find themselves in. And this is especially true in a dynamically-typed language where frequently errors are raised far (both spatially and temporally) from where the actual error occurred.
I don't think that is weird, but I also already knew that 'and' and 'or' are short-circuit operators in Python. 'z' couldn't have been 'y' since the latter was never evaluated. In the case of 'or' then 'y' would've been chosen.
In practice, the only place I make use of 'or' like that is initializing variables. Due to how Python treats mutable default arguments (they are created when the function is defined, not called) you'll see this pattern used:
def foo(a, b=None): b = b or []If you used "b=[]" in the argument list, the state of 'b' would persist across all invocations of 'foo'.
But it's not a question of fine print. As an Ada programmer should I get annoyed that every other language uses short-circuit logical operators rather than having to make it explicit with 'or else'/'and then' like nature intended? No, I should learn the way of doing things in other langauges otherwise we're all stuck programming to the lowest common denominator of expressibility and that means we're all stuck writing Algol60.
if 5 < x < 10: #Do thingCauses most other languages to crash on compilation, should it be verbotten to use that in Python as it would confuse those unfamiliar?
I made a game, it has penguins in it. It's pay what you like on Gumroad.
Currently Ebaying Nothing at all but I might do in the future.
It isn't the fact that `or` in Python is short-circuiting --- in most languages && and || are short-circuiting operators. It's the fact that, in Python, `or` (and `and`) produce non-boolean values which is very non-standard, especially from a types perspective as I pointed out above. The reason why that's the case is to have convenient syntax for "defaulting" values like what you described above. However, rather than lumping that into a non-standard definition of `or`, I'd rather see that be placed into some other operator (or function).
But yeah, I always just try to figure out a language I am working with. There are always things that you should know and what you should expect to see.
Eh. That is how it is implemented. That's exactly the piece of the documentation you have to find to answer Rend's question: oh wait, `or` produces a non-boolean value? What value does it produce then?.
Make sure you graduate, instead of accepting a job that requires you to drop out.
No. Of course, when in Rome, do what the Romans do. But certainly, just becomes the Romans do something in their home, it isn't an ideal thing to do.
Python, in particular, favors convenience over regularity in its semantics. I personally don't like that about the language from both a designer's perspective --- irregularity leads to hard-to-diagnose errors --- and an educator's perspective --- irregularity means more "corners" that a student needs to reason about.
Comparison chaining is one of those conveniences (albeit less offensive because it's more difficult to produce "poisonous" errors from them). In most languages, comparisons are a binary operator so 5 < x < 10 is ill-typed because precedence dictates that we have (5 < x) < 10 and (5 < x) has type bool and 10 is type int which are incomparable things.
In Python, comparisons are not strictly binary. Indeed you can have chains of them, e.g.,
Which is very convenient because this is how we'd normally write comparisons. But because of regularity of syntax, we can also write expressions such as:
Which does not obey our common sense understanding of how comparison chaining works, at least when we write such things on paper --- y = 7 which is not <= 3 so surely the expression is False. By trial-and-error or reading the standard (https://docs.python.org/2/reference/expressions.html#not-in), you can derive what is actually happening:
Which explains why y <= 3 is not checked. To do "the thing you might expect" requires more mathematical smarts (systems-of-constraints solving) than a compiler writer is willing to invest. And so we reach a compromise in language design regularity versus "convenience" where many languages opt for the former (regularity) and Python opts for the latter (convenience). "Convenience" is in quotes because while such semantics enable some common case comparison chaining, they are not general enough to handle all of the cases that the language admits (in the way that you expect, at least).
(EDIT: there's also the whole bit about side-effects in the language as well. Note that it seems like the desugared form of a comparison chain requires that we evaluate each of e2 ... em-1 twice. If these expressions contained side-effects, then those side-effects would be evaluated twice. Thankfully, the Python standard notes that each expression is explicitly only evaluated once in the usual short-circuiting fashion even though the expanded form suggests otherwise.)