|
qntm posted:Here we also see that just because something is more powerful doesn't mean it's better. forEach should almost always be used over for(;. Well, this is "powerful" in a similar sense as an infinite-tape Turing machine is powerful or assembly code is powerful. Capability does not imply ease of use. I never really had a big problem with Python list comprehensions. They're weird, that I will definitely grant, but they're not awful to read as long as you don't try to compound them. Python's scoping rules are far more annoying.
|
# ? Jan 20, 2016 18:52 |
|
|
# ? May 30, 2024 12:14 |
|
You should use whatever communicates the intent best, so yeah mostly this means using forEach instead of for when appropriate. It took me a while to get used to this in Common Lisp, as it has a pretty huge overlapping set of functions like that, plus the 'loop' mini-language.
|
# ? Jan 20, 2016 18:58 |
|
Subjunctive posted:I think Perl5/Perl4 had that problem, and it's certainly common enough with frameworks which have other libraries around them (angular, react, etc.). Also, Swift breaks poo poo all the time.
|
# ? Jan 20, 2016 19:02 |
|
qntm posted:Here we also see that just because something is more powerful doesn't mean it's better. forEach should almost always be used over for( ; ; ). Right, this is exactly the point I was making on the previous page: a good principle is to use the least powerful construct you reasonable can to get the job done.
|
# ? Jan 20, 2016 19:12 |
|
comedyblissoption posted:
The Python thread makes fun of me when I post code like this but I like the toolz library for a functional style in Python. Python code:
|
# ? Jan 20, 2016 19:19 |
|
ratbert90 posted:Strewn about the project I inherited are C files, in these C files are bullshit like this: Seriously, apart from the brace placement and missing error checks this is perfectly clear and even nicely documented. Every one of these statements has a purpose. You just seem to lack the information needed to understand why someone would want something like it. As far as I can tell, this is intended to start a daemon process, avoiding several pitfalls caused by various warts of UNIX-like systems: - The chdir avoids leaving a reference to the original working directory. - Closing all file descriptors (portably, even) similarly avoids leaving references to other files, and prevents information to leak to the started process. - setsid prevents signals to be propagated from the parent's process group to the new daemon (think Ctrl-C). - I think the setuid is to make the process run as the real root user; I assume that the program will have its setuid bit set to make this work. Finally, chkconfig is a utility that installs a symbolic link to a startup script to be run at boot time, and the last statement runs that script explicitly so the daemon starts up immediately.
|
# ? Jan 20, 2016 21:45 |
|
HappyHippo posted:Right, this is exactly the point I was making on the previous page: a good principle is to use the least powerful construct you reasonable can to get the job done. I think "general" may be a clearer word here than "powerful".
|
# ? Jan 20, 2016 21:58 |
|
Zopotantor posted:Seriously, apart from the brace placement and missing error checks this is perfectly clear and even nicely documented. Every one of these statements has a purpose. You just seem to lack the information needed to understand why someone would want something like it. Yeah, it's an unusually good example of subprocess invocation. You want to have as clean a context as possible. Those commands typically need to run as root, so it might well exist so that it can be made setuid, which is a bad idea with a simple shell script.
|
# ? Jan 20, 2016 22:09 |
|
Internet Janitor posted:If I list specific cases they're going to get picked to death Fair enough you called me out for this before I did it, but I still will do it. The behaviour of comparison operators is Good and the only pity is that it's not done that way by all other languages. I don't know what you mean about "unintuitive consequences for operator precedence". You say it gives students a "wrong understanding of how logical expressions work"; how so? They will get the right idea about how they work in Python, certainly. If they try to write chained comparisons in the same way in other languages where comparisons work in the C way, then sure they will run into bugs the first time. That's the fault of other languages for doing things a silly way, rather than Python's for doing things right. Your original post referred to "inconsistencies and special cases", but if anything Python bends over backwards to be consistent in its treatment of chained relational operators; to the extent that every relational operator (including is and in) behaves the same way. "0 < 2 in [0, 1]" is equivalent to "0 < 2 and 2 in [0, 1]" (which would evaluate to False). As for the second point, I would like to see what a Python that required you to explicitly declare variables would be like. Implicitly declared variables are, I think, the part of Python's dynamic execution model that I like the least. It also seems to me to go against the "explicit is better than implicit" thing that is supposedly a guiding principle of the language. I don't really understand the fuss about list comprehensions going on itt at the moment. Sometimes they are useful, sometimes not, like any other tool. I find it hard to see what's especially difficult to follow about them.
|
# ? Jan 20, 2016 22:09 |
|
Thermopyle posted:Every time anyone posts stuff like that about any language I find myself going "oh yeah that's terrible, what a dumb language". If you're coding for yourself, no matter how "bad" the language is, you'll likely find a subset that works for you and acclimate to it, and it'll become "not so bad". Once you start working in a team and reading other people's code though, you're out of luck. No matter how good their style is, the only thing holding them back is the language. And you'll slowly grow to hate them all.
|
# ? Jan 20, 2016 23:11 |
|
HappyHippo posted:In addition to what fritz said, I was referring to a "typical for loop" where you just loop from one value to another. Doing weird poo poo is normally obvious, although not always. I'm not a fan of the c style for loop party for this reason. For example you could modify the iteration variable in the loop, which is why you should use foreach in place of for where possible (in languages that have it), again because it's less powerful. Ok, when "for" was mentioned specifically in the context of use instead of "while", I assumed that you meant the C style for loop, which didn't make sense to me for exactly this reason: Plorkyeran posted:For can be used for everything foreach can, but not vice versa. Therefore for is more powerful. in that "for" (as in, for (i = 0; i < max; i++)) can be used for everything "while" can, but not vice versa (or at least, not as trivially). If you were referring to foreach/iterator/for comprehension constructs, then that makes sense. On the subject of list/for comprehensions vs filter, I feel obligated to mention that in Scala, they're the same thing (in that for comprehensions are syntactic sugar for combinations of map/flatMap/filter)
|
# ? Jan 20, 2016 23:15 |
|
fritz posted:You can't always modify the loop counter in a for. I wondered the same thing. Mostly because I mainly use languages like C where you totally can. I always saw for and while as equivalent in power, just that for had a special place for initializing and modifying a counter variable, and that if the last statement in the loop body is i++; or something similar, you should use a for loop, as it would be far clearer than a while. And of course theres for (;X;), which is identical to while in C.
|
# ? Jan 20, 2016 23:19 |
|
Zopotantor posted:Seriously, apart from the brace placement and missing error checks this is perfectly clear and even nicely documented. Every one of these statements has a purpose. You just seem to lack the information needed to understand why someone would want something like it. System is bad and shouldn't be used. Not checking return codes. I wrote the exact same thing as a bash script and it worked fine (from the callout in the code that calls this) I integrated the callout into the code that called this code and it worked fine. There's no reason to make an entirely separate C program that calls system and doesn't check return codes to do this job.
|
# ? Jan 20, 2016 23:52 |
|
Hammerite posted:Fair enough you called me out for this before I did it, but I still will do it. The behaviour of comparison operators is Good and the only pity is that it's not done that way by all other languages. I don't know what you mean about "unintuitive consequences for operator precedence". You say it gives students a "wrong understanding of how logical expressions work"; how so? They will get the right idea about how they work in Python, certainly. If they try to write chained comparisons in the same way in other languages where comparisons work in the C way, then sure they will run into bugs the first time. That's the fault of other languages for doing things a silly way, rather than Python's for doing things right. it's bad because it doesn't make sense in most cases. "0 < 2 in [0, 1]" is nonsensical. well-defined nonsense is still nonsense. it's inconsistent because it's a special sugar that only applies to relational operators. so now people learning about expressions have to learn a special thing about relational expressions, instead of just having a simple mental model of what binary operators do. is it worse than hitler? probably not. but that doesn't make it good. it's needless complexity to save a few keystrokes, and that is not good.
|
# ? Jan 21, 2016 00:07 |
|
zergstain posted:I wondered the same thing. Mostly because I mainly use languages like C where you totally can. That's why I said "always" instead of "ever".
|
# ? Jan 21, 2016 00:56 |
|
SurgicalOntologist posted:The Python thread makes fun of me when I post code like this but I like the toolz library for a functional style in Python. i know the javascript underscore library has a similar workaround (not sure if it uses lazy evaluation)
|
# ? Jan 21, 2016 02:06 |
|
Zopotantor posted:Seriously, apart from the brace placement and missing error checks this is perfectly clear and even nicely documented. Every one of these statements has a purpose. You just seem to lack the information needed to understand why someone would want something like it. Using system instead of one of the exec family functions is pretty gross, but it's probably safe, if there aren't any dangerous environment variables that don't get stripped out by libc. edit: although, closing all of the file descriptors is a little questionable (stuff like this can happen if a process expects stdin/out/err to exist) Hammerite posted:The behaviour of comparison operators is Good and the only pity is that it's not done that way by all other languages. I don't know what you mean about "unintuitive consequences for operator precedence". You say it gives students a "wrong understanding of how logical expressions work"; how so? They will get the right idea about how they work in Python, certainly. If they try to write chained comparisons in the same way in other languages where comparisons work in the C way, then sure they will run into bugs the first time. That's the fault of other languages for doing things a silly way, rather than Python's for doing things right. No, actually, it's loving terrible. `False == False is False` being desugared into `False == False and False is False` is absurd. b0lt fucked around with this message at 02:55 on Jan 21, 2016 |
# ? Jan 21, 2016 02:45 |
|
comedyblissoption posted:List comprehensions are kind of dumb because they aren't extensible. Holy gently caress you just made functional langs click so hard.
|
# ? Jan 21, 2016 04:22 |
|
All that fancy monad poo poo is just Haskell's version of a terrible ruby DSL
|
# ? Jan 21, 2016 04:25 |
|
Chained comparison sucks because it completely fucks with operator arity and precedence, turning comparison operators into weird pseudo-mixfix ops depending on their environment (in "2 < 3 < 4", the two "<"s have completely contrary signatures - one doesn't even return a boolean.)
|
# ? Jan 21, 2016 04:57 |
|
Also LINQ is clearly superior to Python's comprehensions, and I wish more than just the C# family would use it (though Microsoft probably has a patent on it or something.)
|
# ? Jan 21, 2016 05:06 |
|
Asymmetrikon posted:Also LINQ is clearly superior to Python's comprehensions, and I wish more than just the C# family would use it (though Microsoft probably has a patent on it or something.) Do you mean the weird other syntax embedded in C#? Because the library itself isn't exactly novel.
|
# ? Jan 21, 2016 05:09 |
|
I had a prototype of LINQ for JavaScript and Microsoft...hinted that they would napalm the standards process if I brought it to ECMA. I don't know if it's patented, but at the time at least MSFT was very proprietary about it.
|
# ? Jan 21, 2016 05:11 |
|
Yeah, the EDSL. It's a relatively clever way to integrate monadic operations into imperative code with syntax that's familiar to a lot of people.
|
# ? Jan 21, 2016 05:13 |
|
fritz posted:That's why I said "always" instead of "ever". I'm guessing in those languages there actually isn't a for loop, and you have to use a foreach loop where the container is an integer sequence of some kind. That seems to be the case in Python. And I admit to having to check.
|
# ? Jan 21, 2016 05:15 |
|
comedyblissoption posted:
The APL family makes this style of composition even simpler. In K, most functional combinators have single symbols- / is over/reduce, # can mean filter in certain contexts, ' is each/map, etc. The above would look like: code:
Since "over" understands that 1 is the natural starting point for a product and the multiplication operator naturally generalizes to vectors you can simplify the expression further without changing its meaning: code:
|
# ? Jan 21, 2016 05:51 |
|
A language's norms and conventions are established by its community. JavaScript and Python are exceptionally similar, to the point where JavaScript 2.0 lifted features and syntax nearly directly from Python. And yet, the Python code I write and the JavaScript code I write are fundamentally structured very, very differently. I use different idioms in each, because I know that the general communities of Python like certain features and certain styles, and dislike others. JS tends to be very callback and function heavy, with event listeners and promises everywhere, so the map and filter style of JS is natural to those communities. But with Python, you tend to prefer simpler kinds of list comprehensions that use named functions. You can even see this in the styles of itertools vs. underscore, and with clever helpers like defaultdict being a central part of Python's iconic terseness, whereas JS has no direct equivalent. Of the warts that IJ mentions, the scoping one is really the only one that really gets me. And when I need to, I use a dumb trick to work around that: Python code:
|
# ? Jan 21, 2016 07:01 |
|
Soricidus posted:it's bad because it doesn't make sense in most cases. "0 < 2 in [0, 1]" is nonsensical. well-defined nonsense is still nonsense. It is true that "0 < 2 in [0, 1]" is code that you shouldn't write; I'm not advocating writing things like that but I am advocating that writing things like 2 < x < 5 is natural and sensible and that the other relational operators behaving in a compatible way is a necessary price to pay in consistency for that goodness. If you see someone actually writing code like "0 < 2 in [0, 1]" you have my permission to shun them! quote:it's inconsistent because it's a special sugar that only applies to relational operators. so now people learning about expressions have to learn a special thing about relational expressions, instead of just having a simple mental model of what binary operators do. Relational operators are legitimately a different kind of operator than others, and it's fine for them to behave differently. In mathematics, you wouldn't write something like "2 < 3 < 4" and expect people to see that as equivalent to "(2 < 3) < 4" where "2 < 3" is an expression in its own right to be evaluated as either 0 or 1. (or whatever the associativity of < usually is, I haven't checked and don't care.) It's good that Python forces you to explicitly parenthesise if that's the expression you want to write. It's good that Python enforces behaviour of relational operators that is similar to what you would see in written mathematics. It is every language that does things differently that has got it wrong. b0lt posted:No, actually, it's loving terrible. `False == False is False` being desugared into `False == False and False is False` is absurd. Nuh uh
|
# ? Jan 21, 2016 10:37 |
|
Steve French posted:In what way is for less powerful than while? You can implement a for loop using while (some variant of the yourdon loop I guess) but your going to end up getting your hands dirty implementing many of the while use cases with for. At least in the python iterator/generator sense of for:
|
# ? Jan 21, 2016 10:55 |
|
If Python was so committed to imitating written mathematics maybe its matrices wouldn't multiply pointwise by default.
|
# ? Jan 21, 2016 12:23 |
|
qntm posted:If Python was so committed to imitating written mathematics maybe its matrices wouldn't multiply pointwise by default. I remember reading about the matrix maths provisions in Python when they introduced the @ operator. I don't really recall much about it (I don't use Python for anything involving matrix maths) but I have a feeling I might well agree with you. I don't think Python is above criticism, and I have my own things I don't like about it, they just happen to have got a lot of things right.
|
# ? Jan 21, 2016 13:39 |
|
Quick fun code snippet unrelated to the discussion at largePython code:
|
# ? Jan 21, 2016 16:31 |
|
Reformed Pissboy posted:Quick fun code snippet unrelated to the discussion at large What was this in aid of? There are various ways to do the same thing with much less repetition, and likely more reasons than that to not do such a thing at all...
|
# ? Jan 21, 2016 16:35 |
|
Ultimately, to change the color of some lines to indicate where fluid/air is in a pump system. I should also mention that's part of an 800-line __init__(), in an 8600 line module. It's really ...something. the __init__, by the way, ominously ends with: Python code:
|
# ? Jan 21, 2016 17:05 |
|
|
# ? Jan 22, 2016 05:49 |
|
I could see that being pretty readable if you get used to it and it's not abused to be overly clever. Getting rid of currying does make that style of composition simpler. I see the terser symbols as orthogonal to its simplicity. I think it'd be fine as well if the symbols were replaced w/ english words. I think most working programmers would choose to barf seeing the example w/ terse symbols.
|
# ? Jan 22, 2016 06:01 |
|
qntm posted:If Python was so committed to imitating written mathematics maybe its matrices wouldn't multiply pointwise by default. Python doesn't have matrices. The third party library NumPy has arrays, which are different things than matrices (obviously), for the reason that they are incredibly useful. (i.e., the person that wrote NumPy made a thing that solved the problem they had in front of them, instead of some different problem, go figure.)
|
# ? Jan 22, 2016 06:32 |
|
comedyblissoption posted:I think it'd be fine as well if the symbols were replaced w/ english words. K has fairly flexible rules for currying and compounding, so you can make it about as readable as you could want: code:
|
# ? Jan 22, 2016 07:34 |
|
Internet Janitor posted:It's the only language I've worked with that I can type as fast as I can think. Really? I don't type especially fast but I've never felt that typing takes up a significant proportion of my time. The time spent thinking dwarfs it, even when writing all new code in comparatively verbose languages (mainly C++).
|
# ? Jan 22, 2016 10:22 |
|
|
# ? May 30, 2024 12:14 |
|
Rottbott posted:Really? I don't type especially fast but I've never felt that typing takes up a significant proportion of my time. The time spent thinking dwarfs it, even when writing all new code in comparatively verbose languages (mainly C++). This is why I've never been particularly wooed by those ultra-nerdy text editors Linux people use, vim and emacs and what have you. Advocates go on and on about how quickly they can move around a file and edit but I never feel like how quickly I can edit the file is a bottleneck, it's how quickly I decide on the right thing to do.
|
# ? Jan 22, 2016 11:08 |