Live data from Hacker News

Why Operators Are Useful

neopythonic.blogspot.com

161–170 of 173 posts

Re: Why Operators Are Useful

#161
post #52

Earlier quoted context omitted.

That’s semantically not an “add”, it’s a “merge” or “update”

What happens when you “merge” a pile of six pennies with a pile of three pennies? You get a pile of nine pennies. Six plus three is nine. Adding three pennies to six pennies results in a single group of nine pennies. My point: don’t just pick words, explain why those words were chosen.

Problem with pennies as your example is it's hard to see how these work into a key value context.

If Penny is a class, then maybe you're asking what happens when you combine two arrays (or Python lists) of Penny objects? You get one array (list) containing all the Penny objects.

Perhaps you're getting at something like what if you have two "wallet" dictionaries you want to merge?

Let's say each wallet dict has a list of Penny objects, Dime objects, $5 notes, etc. If you are merging the wallets, maybe you don't want to overwrite the first wallet's Penny list with the second wallet's Penny list and instead you want to combine them.

This is where a dictionary comprehension can come in handy. Just iterate on the second wallet's items and add each item's value to the first wallet's corresponding value at the same key to create a new wallet object (or update one of your two existing wallets by setting the wallet equal to the comprehesion). You would have to add additional logic if you had any nested dictionaries in your wallet dictionary or another type that doesn't combine with the + operator, such as sets.

The other case is something like when your wallet gets sent off to the thief api. To make this more Pythonic, let's say you have a cached idea of your wallet's contents before your wallet itself is sent over the api. Once your actual wallet comes back and you pull it out to pay for something and realize it's empty, you merge the wallet you're holding with the cached idea of the wallet in your head, effectively updating the wallet to empty. If the key values are still on your returned wallet's dict, just now they're a bunch of empty lists as values, this will work fine:

    cached_wallet.update(my_wallet)
However, if the key value sets are removed entirely from the wallet returned by the thief api, you'd probably be better off doing:

    cached_wallet = my_wallet
This is because in Python the first example would have no affect on your cached idea of the wallet because an empty dict passed to the update method will not modify the dict you're attempting to update. So actually the second approach is much more robust here, unless of course it's problematic for some other part of your system to have a keyless wallet floating around (although I'd suggest fixing those other parts of your system by having defaults in place).

You could also use a dictionary comprehension in this case, making use of the get method with defaults while iterating on the emptied wallet you're holding like this maybe:

    cached_wallet.update({
        k: my_wallet.get(k, type(v)()) for k, v in cached_wallet.items()
    })
If the thief put a new key value pair in your wallet, you wouldn't get it in the above comprehension, so you might want to do this in some cases:

    cached_wallet.update(
        **{ k: my_wallet.get(k, type(v)()) for k, v in cached_wallet.items() },
        **my_wallet,
    )
Although that may be called out as more expensive/redundant than necessary, you may want to combine the .keys() from both dictionaries, cast them as a set to dedupe then iterate through the actual wallet on those and fuck all, you're tossing the dirty tissue he stuffed into your wallet in the garbage anyway ... but then actually you decide to keep it, there may be DNA evidence here ... you have no idea how you're going to actually parse and apply this evidence and it's kinda disgusting and, ugh, get a hold of yourself, toss that out and go wash your hands and then focus on making sure the credit cards that are missing are canceled and hope to God that updating your card number on your Fubo TV streaming account doesn't invalidate your legacy subscription that lets you watch the Barcelona game each weekend for $10/mo because there's no way in hell you're going to start paying them $40/mo, that's bullshit.

Re: Why Operators Are Useful

#162

Earlier quoted context omitted.

I happen to think baking unicode into your concept of a string is fundamentally misguided, so that all string operations following from that premise are inherently wrong. The very first example, constrasting encoded byte length with String.length("é")=1, calling the latter the "proper length" walks into a shibboleth which puts Elixir on the side of String.length("ﷺ")=1, even with the grapheme clusters concept, for wh…

I could be wrong, but I think the reason why String.length is one is to have a consistent idea of what happens when you have monospaced console output. Things in the elixir standard library exist "when you need them for elixir itself", and monospaced console output formatting working is needed in a few parts of elixir. If you care about bytes only, you can use byte_size, as indicated in the docs.

No, codepoint length is totally useless for monospaced console output, see the third example. Grapheme clusters are closer, but still wrong in the presence of wide characters.

Re: Why Operators Are Useful

#163

Earlier quoted context omitted.

Not true. Division isn't associative and you can do e.g. (/ 12 6 3)

This is true - Lisp is making / left-associative. But this observation does not change my point: that the parent comment is saying "Lisp already has the ability to do + on lists", but the reason "+ on lists" makes sense is because Lisp is using the underlying associativity of mathematical +. And the latter associativity property, for abstract mathematical "+", is what the blog post is describing/exploring.

The computing + is not associative for inexact types like floating-point. That's why it's important for the Lisp + to be consistently left-associative; the result could vary if that were left to the implementation to do however it wants.

In addition/relation to floating-point, another way in which addition is not associative in computing is if there are type conversions. (+ 1 1 0.1) is not the same as (+ 1 (+ 1 0.1)). The former will do an integer addition to produce 2, and then that is coerced to 2.0 which is added to 0.1. The latter adds 1.0 to 0.1, and then adds that to 1.0: two floating-point additions.

In languages that don't have bignums (which could include some Lisp dialects) whether overflows occur can depend on the order of operations, even when all operands are integers.

The reason we can have a n-ary + is that three or more arguments can be decimated through a binary +. The concept of + is defined as a binary operation.

Lisps have variadic functions that are blatantly non-associative, like, oh, list. (list 1 2 3) isn't (list 2 3 1).

Re: Why Operators Are Useful

#164

Earlier quoted context omitted.

this is equally untrue true for strings, of course. “foo”+”bar” != “bar” + “foo” there are valid non-commutative additions.

An interesting example is C's pointer-integer addition. p + n == n + p, true, but this is a purely syntactic fact. The actual semantic question of commutativity, whether switching the order of the arguments leaves the value unchanged, cannot even be asked of pointer-integer addition since the arguments, having differing types, cannot be switched.

Indeed in C even array[index] is equivalent to index[array], just in case you want to be confusing.

Re: Why Operators Are Useful

#165

Earlier quoted context omitted.

I could be wrong, but I think the reason why String.length is one is to have a consistent idea of what happens when you have monospaced console output. Things in the elixir standard library exist "when you need them for elixir itself", and monospaced console output formatting working is needed in a few parts of elixir. If you care about bytes only, you can use byte_size, as indicated in the docs.

No, codepoint length is totally useless for monospaced console output, see the third example. Grapheme clusters are closer, but still wrong in the presence of wide characters.

I've written a fuzzing library that tests random Unicode inputs and the width of the output was sensible on three platforms (Linux, Mac, and powershell).

Re: Why Operators Are Useful

#167

I'm amazed (and horrified) how come such an intelligent mathematician and designer of a beautiful programming language made such an obvious fuckup of using a commutative operator for string concatenation. Really, I hate python just for this single idiotic notation. I mean, it's right there in front of your eyes. He talks about the convenience of using a visually commutative operator like "+" for commutative operation…

Hmm it does look like the other comment responding to you is correct: + is not always commutative in math: http://mathworld.wolfram.com/OrdinalAddition.html. If mathematicians are fine with that, I'm not sure what argument you may have against this operator being non-commutative in a programming language.

Re: Why Operators Are Useful

#168
post #8

Operators can certainly be nice. And I do like allowing the programmer to create new ones too, though I'd tend to prefer the Haskell approach of creating new ones out of existing symbols like >< or such rather than the C++ approach of letting the programmer redefine an existing operator for a new use, << in the streams library being one of the worst common examples.

Every C++ programmer knows that So you really did pick the worst common example to illustrate you point... A good example is how "&" is used by boost serialisation to allow both serialisation and deserialisation of a value using the same expression:

    obj & value;
Now that makes no sense at first sight. Still, not even this example can be used as an argument against operator overloading, because operators are just functions with predefined names and some expected behaviour.

The above could have been called as obj.serializeOrDeserialize(value) and it wouldn't have been much better. The problem is with the programmer that can't pick proper function names (where +, -, etc are also function names).

Re: Why Operators Are Useful

#169
post #25

he doesn’t make any coherent argument as to why one is more clear or preferred than the other. he simply states it and moves on with this bias. for example, when he compares 2 to 2a, i feel he doesn’t really address anything and just states his preference as the more clear one. plus, he of course seems to know nothing about lisp (or just ignores it) where you might have: (+ a (+ b c)) = (+ (+ a b) c) = (+ a b c) all…

> doesn’t really address anything and just states his preference as the more clear one Maybe he doesn't understand why one is less confusing to him than the other one. Doesn't mean it's not like that for most people though. The reason it's less confusing is familiarity and simplicity (it's simpler form and it's already familiar).

but isn’t implied operator precedence and using parentheses to group and control order of operations one of the things people often find confusing in mathematics, despite it being familiar?

Re: Why Operators Are Useful

#170

Earlier quoted context omitted.

Possibly gp was referring to other, well known writing by the author? I assume all have seen GVR on tail call optimization.

Maybe, but given that it was the opening to the comment with no reference to anything else it just seems like an unqualified opinion in the vein of the comenters criticisms of the post. It's gone now so I guess OP agreed.

i agreed it was unnecessary, but i don't think it's a huge stretch. most of the stuff i have read from him has come across as someone who has made up their mind and that's that. it's like when you ask someone why something is and the answer you get back isn't thoughtful, insightful, revealing, etc. but instead beats around the bush such that it reads like the person either doesn't understand or its because that's simply the way they want to do it. which is fine. python is (was?) his language, but i don't have to enjoy the perspective and approach. he no doubt knows way more than i do, but i never learn anything from him.

see here for some examples: https://developers.slashdot.org/story/13/08/25/2115204/inter...

almost every answer is basically "i like to be pragmatic" but neither the design of python or his answers reflect that.

so now that python is so popular, we have people completely unaware of the existence of languages like lisp/scheme and ml dialects, which are much more powerful and can be just as clean as or cleaner than python, and a stunted language taking over every project.

Post reply on HN