HN user

palotasb

458 karma

boldizsar.palotas at gmail.com

https://github.com/palotasb

Posts2
Comments90
View on HN

The author is perhaps presenting a good argument for languages/runtimes like JavaScript/Node where dependencies may be isolated and conflicting dependencies may coexist in the dependency tree (e.g., "app -> { libpupa 1.2.3 -> liblupa 0.7.8 }, { libxyz 2.0 -> liblupa 2.4.5 }" would be fine), but the proposed dependency resolution algorithm...

Our dependency resolution algorithm thus is like this:

1. Get the top-level dependency versions

2. Look up versions of libraries they depend on

3. Look up versions of libraries they depend on

...would fail in languages like Python where dependencies are shared, and the steps 2, 3, etc. would result in conflicting versions.

In these languages, there is good reason to define dependencies in a relaxed way (with constraints that exclude known-bad versions; but without pins to any specific known-to-work version and without constraining only to existing known-good versions) at first. This way dependency resolution always involves some sort of constraint solving (with indeterminate results due to the constraints being open-ended), but then for the sake of reproducibility the result of the constraint solving process may be used as a lockfile. In the Python world this is only done in the final application (the final environment running the code, this may be the test suite in for a pure library) and the pins in the lock aren't published for anyone to reuse.

To reiterate, the originally proposed algorithm doesn't work for languages with shared dependencies. Using version constraints and then lockfiles as a two-layer solution is a common and reasonable way of resolving the dependency topic in these languages.

Sourcehut

Is it there yet?

Notice: sr.ht is currently in alpha, and the quality of the service may reflect that. As such, payment is currently optional for most features, and only encouraged for users who want to support the ongoing development of the site. For a summary of the guarantees and limitations that the alpha entails, see this reference.

https://sourcehut.org/pricing

The spiral rule works only if there is no pointer to pointer or array of array in the type. In other words it is an incorrect rule. But take this for example:

        +----------------------------+
        | +-----------------------+  |
        | | +------------------+  |  |
        | | | +-------------+  |  |  |
        | | | | +--------+  |  |  |  |
        | | | | |  +--+  |  |  |  |  |
        | | | | |  ^  |  |  |  |  |  |
    int * * ¦ ¦ ¦ VAR[1][2][3] |  |  |
     ^  | | | | |     |  |  |  |  |  |
     |  | | | | +-----+  |  |  |  |  |
     |  | | | +----------+  |  |  |  |
     |  | | +---------------+  |  |  |
     |  | ---------------------+  |  |
     |  +-------------------------+  |
     +-------------------------------+
The type of VAR is a [1-element] array of [2-element] array of [3-element] array of pointer to pointer to ints. I drew a spiral that passes through each specifier in the correct order. To make the spiral correct it has to skip the pointer specifiers in the first three loops. This is marked by ¦.

The Right-Left Rule is quoted less frequently on HN but it's a correct algorithm for deciphering C types: http://cseweb.ucsd.edu/~ricko/rt_lt.rule.html

The spiral rule can be modified to process all array specifiers before all pointer specifiers, but then you'd have to specify that the order to do so is right and then left. At that point it's just the Right-Left Rule.

https://www.theorieexamen.nl/theory-exam/what-is-a-entrance-...

An entrance or exit construction is a place on a road where you aren't just turning onto the road but exiting the road entirely. The most common example from any country would be a private driveway. Pedestrians, cyclists and cars going along the sidewalk, bike path or road have priority against anyone turning into the driveway or turning onto the road from the driveway.

The Netherlands generalizes this concept to some low-priority side streets. If there is a continuous sidewalk (i.e., the cars go up a bump to the level of the sidewalk as opposed to the pedestrians stepping down from the sidewalk to the level of the street). This is not the case in this specific intersection.

Correct, only one.

This specific turn is onto a street that the article describes as "traffic volume here is low, since only residents will use this street." They probably expect the 1-car buffer to be enough for this intersection. You can see in the video that the 1-car buffer is empty most of the time.

For intersections where they expect more turning traffic (where the one car buffer wouldn't be enough), they add turning lanes that can accomodate more than one car. You can see an example of this a few hundred meters northeast when Graafseweg intersects the Van Grobbendocklaan: https://maps.app.goo.gl/ZmURqawr3oeBX5Sq9

> using the password recovery flow

use a key/password

The previous poster intentionally mentioned password recovery flow. If you can gain access without your password, than law enforcement can too. If you could only gain access with your password, you could consider your data safe.

Raw integers are also valid JSON according to the spec: https://www.json.org/json-en.html

json is defined as one element

element is defines as ws (whitespace), value, ws

value is defined as one of: object, array, string, number, "true", "false", "null"

Wrapping in {} to make an object or in [] to make a list (which is also not an object) is not necessary to make a valid JSON document. This is also discussed in the Stack Overflow question linked.

The Stroad 3 years ago

As someone living in Amsterdam, Netherlands, I don't understand the resistance. I agree with the article and I think it is advocating for the right thing, so it's the right kind of propaganda.

Maybe there is more common ground between you and Strong Towns than you'd think? They don't just advocate for "bike bros." Here everyone bikes from kids in elementary school to their grandparents. The key is having separate car infrastructure (roads, highways) and biking/pedestrian infrastructure (streets, bike lanes, pedestrian-only areas).

The net effect is that many people here choose non-car transport (public transport, biking, walking), which reduces traffic. This also makes getting around by car more efficient, for destinations where you need to use a car, because there is less traffic.

If you want to live in a single-family home in the suburbs and own a car, you can do that here too. It's fine because there are roads to get around the country. Not stroads though, so no need to worry about pedestrians or cyclists when you're on a road, so they allow moving faster.

If you want to live in an apartment in the city without owning a car, you can do that here too. It's fine because there is public transport, proper bike lanes and streets to get around the city. Not straods though, so no need to worry about cars.

I'd say it's both nicely looking and quite efficient. Not sure by what metric would an American city be more efficient, but generally I wouldn't want to trade places.

abs(x) = x*sign(x)

True in 1 dimension, but not in higher dimensions, because, as you say:

how would you define sign(x) in a higher dimension?

abs(x) is generally defined as distance of x from zero.

The fact that sqrt(x^2) or x*sign(x) happen to give the same result in 1 dimension doesn't necessarily imply that they can be applied in higher dimensions as-is to result in abs(x) with the same meaning. Although sqrt(x^2) is close, but the way to generalize it is sqrt(sum(x[i]^2)).

bool is explicitly documented to be a subclass of int [1][2], so while it might be an obscure feature, or subjectively not someone's preferred style, I don't see any typing related issue. In general I don't think that treating an object as if it were an instance of one of its base classes is weak typing.

[1] https://docs.python.org/3/library/functions.html?highlight=s...

[2] https://docs.python.org/3/library/stdtypes.html#boolean-valu...

From the game's rules:

You might know of some rule in your jurisdiction which overrides local rules, and allows certain classes of vehicles. Please disregard these rules; the park isn't necessarily in your jurisdiction. [...] please answer the question of whether the rule is violated (not whether the violation should be allowed).

You:

obviously police and ambulances (and fire trucks) doing their jobs don't have to follow the sign

Even having read your reply it is not obvious to me what you answered. Did you answer yes, the police etc. are violating the rule only adding a note for us tha, or did you answer no, thinking that this doesn't count as a violation?

To me the overall discussion, but especially the disagreement about emergency services and bicycles proves the point of the original article.

As a counterpoint, Derek Sivers says Simplify: move code into database functions <https://sive.rs/pg>

I think they are both right, Alex Kondov for keeping his domain logic mostly in the application layer, and Derek Sivers for mostly keeping his in the database layer.

Why? Because that's what they know well, and they can keep the domain logic mostly in one place. If Alex can keep most if his domain logic in the application layer that he knows better, that's the better choice for him. If Derek can keep most of his domain logic in the database layer that he knows how to utilize well, that's the better choice for him.

(I can't find it now but I thought someone very smartly reflected on the Why Perl? <https://news.ycombinator.com/item?id=35646612> post today that the main reason why anyone will choose any programming language is that they know how to use it well. I think the same applies here. This is why many programming languages are valid choices for different people and project, and this is why different architectures are valid choices too.)

Ampersand (2015) 3 years ago

[...] A would be read as “A per se A”, [...] I, similarly, would be “I per se I” [...] O would be “O per se O”

That's incorrect, these would have been respectively "per se A", "per se I", and "per se O." The confusion is coming from how the ampersand was listed out in the alphabet:

The alphabet is A, ..., X, Y, Z, and per se and.

That doesn't mean "&" was spelled out as "and per se and" separately. The first and is because it's the last item in a list in a sentence. Only the second and is part of the full phrase of per se and. If you use it as a single item in a sentence, it works like this:

The last letter of the alphabet is per se and.

The last sentence of the article:

the alphabet once ended with a final “X, Y, Z, and & per se &”.

Should be:

the alphabet once ended with a final “X, Y, Z, and per se &”.

To nitpick and to show a cool lambda calculus thing, you can deconstruct booleans if you define booleans and if statements the following way, using only pure functions.

  def TRUE(a, b):
    return a

  def FALSE(a, b):
    return b

  def IF(cond, a, b):
    return cond(a, b)

  assert IF(TRUE, 1, 2) == 1
  assert IF(FALSE, 1, 2) == 2
This gives you the conditional statement in most languages ("cond ? a : b" or "a if cond else b").

One thing I haven't understood yet: After I've bought a house to live in, why does it matter for me whether housing prices go up? Does it matter even if my $X house is worth $3X ten years from now? I assume that I must live somewhere, and any any money I'd earn selling the house, I'd lose buying a new one.

I think a legitimate criticism of this article is using the clickbait "Software 2.0" label for something that's – as very well described by the same article – so very different from "Software 1.0." Considering ALL software, the intersection of uses cases where Software 1.0 and Software 2.0 truly compete are a very narrow niche. In the real world Software 2.0 will thrive in the next decades but Software 1.0 will be there just as much as it is today.

Hi Chris! Thanks for the link, it's an enlightening read, I learned about dynamic variable scopes today.

It did make me change my mind partially about "environment variables are bad for the same reasons global variables are bad." I concur that environment variables are more like constants than mutable globals, even in my language of choice, Python. If you only use them at process boundaries, they is fine, I admit using them that way too:

  parser = argparse.ArgumentParser()
  parser.add_argument("--foo", default=os.environ.get("FOO"))
If they are used at a boundary within a process, however:
  def foo_function():
    return foo_implementation(os.environ.get("FOO"))
Then testing foo_function() becomes a problem because os.environ isn't dynamically scoped within the process. Each test case can set os.environ["FOO"], but then the tests have mutable globals now even if the app doesn't. I know three ways to solve this, each with it's pros and cons:

- 1. Treat the script as a black box, only test the script as a whole -- or not at all. How env vars are used internally doesn't matter. Works well for smaller scripts.

- 2. Keep the code as is, test functions individually by setting and resetting the environment variables in each test setup and teardown. Don't run tests in parallel.

- 3. Push all environment variable usage to process boundaries and make all inner functions pure functions that are only affected by their explicit input parameters. If needed, I even make standard in/out/error, logger instances and other similar globals explicit parameters or class members. Requires more boilerplate, works better for more complex projects. Testing any behavior becomes easier.

I prefer to go with option #1 or #, as #2 feels dirty and makes my test cases smell of workarounds. #3 could look such with few details omitted:

  parser = argparse.ArgumentParser()
  parser.add_argument("--foo", default=os.environ.get("FOO"))
  args = parser.parse_args()

  def foo_function(foo_value):
    return foo_implementation(foo_value)

  def main():
    ...
    foo_result = foo_function(foo_value=args.foo)
    ...

  ...
  
To agree with you, it would be great if the ex-globals-turned-parameters I'm passing around during option #3 would be dynamically scoped. Not shown in the example above, but imagine that instead of printing to sys.stderr, functions receive an stderr: io.IOBase parameter or a custom dataclass that contains such a field. The point is to get rid of mutable global state in all cases.

To disagree with you, I think the correct term for "things the caller knows better than the implementor" are parameters. I'm not sure there's a benefit to preferring dynamic scope for parameters when most languages default to lexical scope.

About your last too points I somewhat agree and somewhat still disagree: "CLI args are usually passed around explicitly" -- I think this is a pro, not a con. Further, CLI arguments are strictly more flexible then environment variables, most argument parsing libraries support key-value parsing in addition to boolean flags and lists.

However, regarding your overall point that I understand as: environment variables used at process bounderies behave like dynamically scoped variables and these are fine. I agree, as long as they stay at process boundaries.

"Files are written to disk" is not strictly true. In the use case where the config contains (hopefully short-lived) credentials, one would pass them in a temporary file that usually only lives in RAM (unless /tmp doesn't use tmpfs or the temporary config file is put somewhere else) and of course doesn't get committed to the repo. (I'm not sure if you meant git commit or filesystem commit.)

I sometimes find secrets to be safer inside config files since so many times the environment variables get dumped into logs – hence all the popular CI/CD products have features to try to scrub such secrets from their logs.

I agree about not using .env files in production, I'd not use it at all.

I find the Twelve-Factor App's design to use environment variable for configuration (https://12factor.net/config) unintuitive and perhaps a bad design choice. I believe environment variables are bad for the same reasons global variables are bad.

Pros listed for env vars include not committing them to the repo and not encouraging grouping them together as environments such as dev, staging or prod. I don't agree that these are always good goals, but if they are, the same can be achieved with config files: don't commit them to the repo, generate them on the fly.

The existence and prevalence of .env files is proof that using environment variables as an alternative has failed. Using Twelve-factor as a reference and .env files at the same time is a bit of a contradiction.

Another alternative to consider for both env vars and config files are command line arguments.