Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe

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.

Adbot
ADBOT LOVES YOU

Beef
Jul 26, 2004
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.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

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.
PHP 4/5 as well, but there weren't actually any PHP 4 libraries worth using so it was okay.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

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.

SurgicalOntologist
Jun 17, 2004

comedyblissoption posted:

code:
//most langs (e.g. python) tend to look like unreadable poo poo:
result = reduce(multiply, filter(predicate, map(square, list)), 1);

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:
import operator
from toolz import pipe, curry
from toolz.curried import filter, map, reduce

@curry
def reverse_args(func, a, b):
    return func(b, a)

pow = reverse_args(operator.pow)
square = pow(2)
mod = reverse_args(operator.mod)
is_odd = mod(2)

data = range(200)
result = pipe(data,
    map(square),
    filter(is_odd),
    reduce(operator.mul),
)
I have no doubt that I'm the horror for trying to straddle two worlds here. It does take a lot of setup with the currying and whatnot to be able to write the pipe line cleanly. If only the operator functions took their arguments in the other order... I should probably learn a proper functional language.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

ratbert90 posted:

Strewn about the project I inherited are C files, in these C files are bullshit like this:

C code:

/*
 * Enables and starts the Blue Alert daemon.
 */

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
	/* Release cwd */
	chdir("/");

	/* Close fds and sockets */
	int fd;
	for(fd=0; fd<sysconf(_SC_OPEN_MAX); fd++) close(fd);

	/* Become process group leader */
	setsid();

	setuid(0);

	system("/sbin/chkconfig PROGRAM on >/dev/null 2>&1");
	system("/etc/init.d/PROGRAM start >/dev/null 2>&1");
}				

what in the gently caress? WHAT IN THE GOD drat gently caress?

Edit* I copy and pasted the whole c file.

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.

Linear Zoetrope
Nov 28, 2011

A hero must cook

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".

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

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.

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.

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.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

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.

SupSuper
Apr 8, 2009

At the Heart of the city is an Alien horror, so vile and so powerful that not even death can claim it.

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".

Then later I find myself using said language without it ever bothering me.

For example, I avoided JS for years because every discussion about it ever highlights all kinds of bullshit. Then I started using it and...it just doesn't bother me.

I'm not claiming that odd/wrong/stupid stuff in a language can't be bad for programmer sanity, because I don't believe that. However, I wonder if talking about an issue just makes it seem worse than it actually is.
I think you hit the nail on the head here. Coding is easy. Reading other people's code is hell. And this thread is basically all about reading other people's code.

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. :devil:

Steve French
Sep 8, 2003

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)

zergstain
Dec 15, 2005

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.

FlapYoJacks
Feb 12, 2009

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.

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.

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.

Soricidus
Oct 21, 2010
freedom-hating statist shill

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.

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).

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.

fritz
Jul 26, 2003

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".

comedyblissoption
Mar 15, 2006

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.

Python code:
import operator
from toolz import pipe, curry
from toolz.curried import filter, map, reduce

@curry
def reverse_args(func, a, b):
    return func(b, a)

pow = reverse_args(operator.pow)
square = pow(2)
mod = reverse_args(operator.mod)
is_odd = mod(2)

data = range(200)
result = pipe(data,
    map(square),
    filter(is_odd),
    reduce(operator.mul),
)
I have no doubt that I'm the horror for trying to straddle two worlds here. It does take a lot of setup with the currying and whatnot to be able to write the pipe line cleanly. If only the operator functions took their arguments in the other order... I should probably learn a proper functional language.
yeah that's as good as you can do in langs like python

i know the javascript underscore library has a similar workaround (not sure if it uses lazy evaluation)

b0lt
Apr 29, 2005

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.

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.

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

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

comedyblissoption posted:

List comprehensions are kind of dumb because they aren't extensible.

List comprehensions are only more readable because the language didn't prioritize good syntax for the superior alternative: composing higher order functions.

here are some examples of different syntaxes for chaining together higher order functions:
code:
//most langs (e.g. python) tend to look like unreadable poo poo:
result = reduce(multiply, filter(predicate, map(square, list)), 1);

//there's probably some list comprehension equivalent for this that looks ok,
//but again, it's not extensible
code:
//some OO langs (e.g. C#) start looking reasonable:
result = list
    .map(square)
    .filter(predicate)
    .reduce(multiply, 1)
code:
//functional langs (e.g. haskell) have idioms supporting composition of functions:
result = reduce multiply 1 . filter predicate . map square $ list

Holy gently caress you just made functional langs click so hard.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
All that fancy monad poo poo is just Haskell's version of a terrible ruby DSL

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
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.)

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
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.)

raminasi
Jan 25, 2005

a last drink with no ice

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.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

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.

Asymmetrikon
Oct 30, 2009

I believe you're a big dork!
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.

zergstain
Dec 15, 2005

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.

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."

comedyblissoption posted:

code:
result = reduce multiply 1 . filter predicate . map square $ list

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:
1*/predicate#{x*x}'list
Evaluates right to left, reads left to right: "Starting from 1, the times-reduction of the predicate-filter of the square of each of the list."

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:
*/predicate#{x*x}list
The K learning curve is pretty brutal (you have to memorize the symbols for about 40 built-in primitives, some familiar and some novel), and some operators are excessively overloaded based on context. Still, when I'm coding in more conventional languages I often find myself wanting to drop into a K one-liner from time to time as a DSL or something.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
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:
class a: pass

a.foo = [1, 2, 3]

def bar():
    a.foo += 9
    print a.foo

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

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

duck monster
Dec 15, 2004

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:

qntm
Jun 17, 2009
If Python was so committed to imitating written mathematics maybe its matrices wouldn't multiply pointwise by default.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

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.

Reformed Pissboy
Nov 6, 2003

Quick fun code snippet unrelated to the discussion at large
Python code:
      self.lineNumbersNames = {
              1:    self.line_1,
              2:    self.line_2,
              3:    self.line_3,
              4:    self.line_4,
              5:    self.line_5,
[...130 lines later]
            135:    self.line_135,
            136:    self.line_136,
            # NOTE: lines: self.line_137 through self.line_140 are not used
            141:    self.line_141,
            142:    self.line_142,
            143:    self.line_143,
            # NOTE: lines: self.line_144 through self.line_276 are not used
            277:    self.line_277,
            278:    self.line_278,
[snip]
            307:    self.line_307,
            308:    self.line_308 }
from a coworker who is brilliant in many embedded areas but not so much at creating UIs in Python (self-taught at both)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Reformed Pissboy posted:

Quick fun code snippet unrelated to the discussion at large
Python code:
      self.lineNumbersNames = {
              1:    self.line_1,
              2:    self.line_2,
              3:    self.line_3,
              4:    self.line_4,
              5:    self.line_5,
[...130 lines later]
            135:    self.line_135,
            136:    self.line_136,
            # NOTE: lines: self.line_137 through self.line_140 are not used
            141:    self.line_141,
            142:    self.line_142,
            143:    self.line_143,
            # NOTE: lines: self.line_144 through self.line_276 are not used
            277:    self.line_277,
            278:    self.line_278,
[snip]
            307:    self.line_307,
            308:    self.line_308 }
from a coworker who is brilliant in many embedded areas but not so much at creating UIs in Python (self-taught at both)

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...

Reformed Pissboy
Nov 6, 2003

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:
# Log the starting free hared drive space
byteformat = "GB"
size, units =  self.get_free_space(r"c:", byteformat)
self.freeSpaceLabel.setText(str(size) + " " + units)
self.logToBrowserWindowAndSysFile("System drive has " + str(size) + " " + units + " of unused memory.")

comedyblissoption
Mar 15, 2006

comedyblissoption
Mar 15, 2006

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.

BigRedDot
Mar 6, 2008

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.)

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."

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:
product: */
odd:     2!
filter:  {x#y}
square:  {x*x}

product filter[odd] square list
But as you say, you can get used to the terser style. I like it because it makes repeated patterns stand out- you begin to recognize idioms and when code isn't written in an overly clever manner you can get the gist very quickly. It's the only language I've worked with that I can type as fast as I can think. Not for everybody or every problem domain, that's for sure, but it's a drat neat little language.

Rottbott
Jul 27, 2006
DMC

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++).

Adbot
ADBOT LOVES YOU

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

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.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply