HN user

throwaway313373

185 karma
Posts0
Comments66
View on HN
No posts found.
Kagi Translate 2 years ago

There is no secret ingredient, Yandex just put more effort into supporting languages that are spoken in ex-USSR countries, because that's the most important market for them.

Other translation tools do not consider i. e. Kyrgyzstan an important market therefore do not put much effort into supporting Kyrgyz.

Kagi Translate 2 years ago

some censorship

How the hell is everyone okay with it?

Why should I be "forbidden" from understanding a text written in a foreign language if it contains something inappropriate?

I don't know of any translation service that does censorship.

Not even Google does it and Kagi was supposed to be less user hostile than Google, not more.

The most interesting idea in my opinion is biased reference counting [0].

An oversimplified explanation (and maybe wrong) of it goes like this:

problem:

- each object needs a reference counter, because of how memory management in Python works

- we cannot modify ref counters concurrently because it will lead to incorrect results

- we cannot make each ref counter atomic because atomic operations have too large performance overhead

therefore, we need GIL.

Solution, proposed in [0]:

- let's have two ref counters for each object, one is normal, another one is atomic

- normal ref counter counts references created from the same thread where the object was originally created, atomic counts references from other threads

- because of an empirical observation that objects are mostly accessed from the same thread that created them, it allows us to avoid paying atomic operations penalty most of the time

Anyway, that's what I understood from the articles/papers. See my other comment [1] for the links to write-ups by people who actually know what they're talking about.

[0] https://dl.acm.org/doi/10.1145/3243176.3243195

[1] https://news.ycombinator.com/item?id=42059605

I always wondered who even decided that averaging the input is a good idea.

It sounds like it makes sense at first glance, but if you think about it a little bit more it actually doesn't make any sense.

The average of two inputs is basically garbage, it doesn't do what either of the pilots want to do and it breaks feedback for both of the pilots.

After watching tons of Mentour Pilot videos (who, by the way, covered [0] this incident) I am convinced that this feature shouldn't exist at all.

And no, I don't think that I'm smarter than people who originally designed this system. I just think that this particular feature was not designed at all. It seems like an afterthought. Like, "hey, there is this corner case that we haven't thought about, what should we do if both pilots input something on the controls? - well, let's just average it, kinda makes sense, right?"

[0] https://www.youtube.com/watch?v=6tIVu0Dpc2o

I think that people who suggest to "just write cleaner code" are missing the point entirely.

Of course, we all are trying to write clear code. It doesn't mean that your tool should make working with less than perfect codebases unbearable.

It is unclear what is the condition of automatic folding of the second level and below.

If you are using "Go to..." a struct declaration or impl in Rust (or a class in other languages) it actually makes a lot of sense. If I'm going to a struct/impl/class I don't know yet which method do I won't to see. If you are just opening a file that you haven't open before though... I'm not so sure.

What does the feature discussed in TFA (chained comparisons) have to do with Python 2 vs Python now.

As another commenter pointed out [0] this feature existed since 1.4 [1].

Also, I don't understand why so many people seem to be so confused/surprised by it. I can't be 100% sure because it was a long time ago, but I think that a lot of tutorials/introductory articles mention it. Like, "Hey, did you know that Python has this cool syntaxic sugar for this thing? Fascinating!". I think that I learned about chained comparisons long before I wrote my first line of Python.

[0] https://news.ycombinator.com/item?id=42038451

[1] https://docs.python.org/release/1.4/tut/node40.html#SECTION0...

"someone who writes code" is very vague. For someone who writes code primarily in Python this behavior is less surprising than the rest that you described.

I can think of some more interesting examples when it violates intuition gained from mathematical notation.

When looking at `a == b == c` we naturally assume that not only `a == b` and `b == c` but also `a == c` because equality is assumed to be transitive.

The problem is that in Python we can make `==` operator to do literally whatever we want, so in Python `==` doesn't have to be transitive.

You may argue that no reasonable person would define equality in such way that is not transitive.

To which I would reply that approximate comparison of floating point numbers looks perfectly reasonable to me.

    EPSILON = 10**-9

    class Foo:
        def __eq__(self, other):
            return other.bar - EPSILON <= self.bar <= other.bar + EPSILON

Rust also gives a custom error message [0] that explicitly explains that "comparison operators cannot be chained" and shows you how to rewrite the expression using `&&`.

Which makes me wonder whether they came up with this idea themselves or if they borrowed it from D.

In any case, I think that this is the only reasonable solution for new languages. Because if you go with C way it will be surprising for people who expect Python way and vice versa. So, making this syntax illegal is the only way to uphold the principle of least astonishment [1].

[0] https://play.rust-lang.org/?version=stable&mode=debug&editio...

[1] https://en.wikipedia.org/wiki/Principle_of_least_astonishmen...

Of course, you're right, it is not possible to to share a connection pool between processes without pgbouncer.

Parent comment is talking about one connection per process with 50k processes.

It is actually not clear what parent comment was talking about. I don't know what exactly did they mean by "front ends".

If you insist on following an honor code while competing against people who are ready to take an unfair advantage of you, you lose.

Between queries in the same transaction? No

Between transactions? Yes, absolutely

In fact, many libraries do it automatically.

For example, SQLAlchemy doc explicitly says [0]:

After the commit, the Connection object associated with that transaction is closed, causing its underlying DBAPI connection to be released back to the connection pool associated with the Engine to which the Session is bound.

I expect other reasonably sane libs for working with transactional databases do the same.

So, if you are doing pooling correctly, you can only run out of available connections if you want to have a lot of long running transactions.

So, why would you want every of your 50k frontends keep an open transaction simultaneously?

[0] https://docs.sqlalchemy.org/en/20/orm/session_basics.html#co...

I think that the main issue here is not treating true/false as values but allowing them to be implicitly converted or compared to numbers with the assumption that true equals 1 and false equals 0.

I think that Rust got this right. It doesn't allow you to add integer to boolean or multiply boolean by float etc, because it is unclear what does it even mean mathematically.

Also, most languages implicitly assume that any value of any type is either "truthy" or "falsy" thus you can do something like `while(1) { do_stuff() }`. Rust doesn't allow this BS, `if` and `while` expect a boolean so you have to provide a boolean.

But it's not a "trick", it's just a normal Python code.

I don't think that anyone who main programs in Python would perceive it as some kind of cool/unusual trick and not just normal code.

Why is it "shocking"?

It's just an architectural decision to spawn a process per connection that Postgres made long time ago.

It's a tradeoff like most decisions.

Back in the days MySQL had huge issues with scaling to multi-core systems (maybe they fixed it now, I haven't used MySQL for a long time) while Postgres never had this problem.

When designing an application around Postgres you just have to take into account that:

1. opening a new connection is rather expensive, so you should have a connection pool

2. opening too many connections is problematic, so you should keep the size of your pool rather small and return connections back into the pool ASAP

That's it.

It's not that hard in practice.