Hacker Newsnew | past | comments | ask | show | jobs | submit | packetlost's commentslogin

> The parentheses are absolutely crucial there for some reason, the { } won't give you pass-through of SIGINT.

This is a gross misunderstanding of what is going on (signals are never "passed through", the process is either in the same group or it isn't), but the real issue here is the confusing semantics of bash's job controls. I personally would have swapped the semantics of { command blocks } and ( subshells ) too, but bash is pushing 40 so maybe it made more sense then.

It will sorta behave properly if you disable job control or put it in a script:

    set +m
    {
        trap 'kill 0' SIGINT;
        for i in {1..$N}
        do
            whatever_command $i &
        done
        wait
    }
it might also kill your current shell too though. This really seems to boil down to not understanding the difference between { } and ( ) in bash.

> signals are never "passed through", the process is either in the same group or it isn't

Yes, I know. It's actually a major nuisance because sometimes you do want to pass the signals through, e.g. to implement termination of all transitive children processes, process groups notwithstanding, so then you have to do it yourself.

> it might also kill your current shell too though.

It absolutely will kill your current shell, but only if it's non-interactive — so that's a funny way to have a script that misbehaves when ran non-interactively, but works as intended when you try to debug it. So, you either need a subshell (and then the subshell having a fresh process group makes it mostly work on its own), or fake it with "trap 'jobs -p | xargs -n 1 kill -SIGINT' SIGINT" bullshit or the like (for all the signals you can remember). The subshell way is somewhat more robust.


> It's actually a major nuisance because sometimes you do want to pass the signals through, e.g. to implement termination of all transitive children processes, process groups notwithstanding, so then you have to do it yourself.

Yes, I would prefer some form of structured concurrency or even just better defaults. Plan9 does it a bit better with rfork and having note groups be its own thing.

> The subshell way is somewhat more robust

Oh it totally is, just trying to illustrate that technically the subshell isn't necessary


Also procmacros add quite a bit of overhead to builds

Note that is so, because macros can have side effects, that was an oversight of Rust design, not having a way to have pure and impure procmacros (macro rules are pure)

It's also worse because the procmacros are themselves Rust and get compiled with the same parameters as the overall build, so if you're running a debug build the procmacros are running as debug binaries.

It's better to think of QPUs as highly specialized coprocessors that do certain things really well. You would only every really use them for problems they're good at. Like ALU vs FPU vs GPU.

What problems are they good at?

Shor's algorithm is the quintessential example, but there are other algorithms (mostly graph algorithms) that are NP and hard would be very efficient on a quantum computer.

> where they benchmark against glibc malloc and glibc is somewhere between 20-150x faster than their implementation

Where are you seeing that?


> Avoiding the heap ... will prevent you from working with substantial amounts of data

This isn't really true of Goose, it's avoiding 'the heap' in the C sense, not in the OS allocated pages of memory sense. One is a programming abstraction provided by the other, but GP is only talking about the programming abstraction. I have never encountered a program that couldn't have memory be explicitly tied to lexical scope, but it can result in less efficient use of it in some cases.

Goose is almost, but not exactly the "allocate all your stuff at the beginning" the programming language. It's honestly the most exciting language I've seen in quite some time.


> I have never encountered a program that couldn't have memory be explicitly tied to lexical scope, but it can result in less efficient use of it in some cases.

> Goose is honestly the most exciting language I've seen in quite some time.

I took a look at its home page [1] and I immediately see red flags:

- Over sixteen benchmarks Goose runs at 3.3x the speed of idiomatic C++, 1.16x hand-optimized C++ and 1.12x the best safe Rust, and uses 1.9x, 1.3x and 1.2x less memory (results). These gains come from Goose's data layouts and memory model.

- push returns a reference to the new element, so a program can link elements while building the array. A vector<T> or Vec<T> may reallocate and cannot provide this guarantee. Stable references account for several benchmark gains.

You're suggesting a performance loss (as expected), but they're claiming a (rather incredible) performance gain?

And they're claiming their vector stable and doesn't reallocate, yet without a performance loss, which makes no sense... it's not a vector anymore. And if you want a non-vector then you can do that in C++ too.

The whole LLM vibe doesn't help inspire confidence either, but even ignoring that, the technical claims themselves are incredible and bizarre, and I'm only a few paragraphs in.

[1] https://aardappel.github.io/goose/


It might be worthwhile to balance these positive claims against the language's own stated limitations [1].

Also, I took a closer look at the actual benchmark results [2]. For memory usage, at least, the median would show Goose using slightly more memory than the well optimized C++ and Rust. It looks like the mean is skewed in Goose's favor by a couple of benchmarks where it does extremely well due to its variable-length enums.

[1]: https://aardappel.github.io/goose/docs/tutorial.html#18-limi...

[2]: https://aardappel.github.io/goose/bench/results.html


> You're suggesting a performance loss (as expected), but they're claiming a (rather incredible) performance gain?

I think part of the reason they’re getting higher performance is that they accept higher memory usage. Memory can be ‘freed’ later than in traditional languages, and the combined size of all stacks will be larger (maybe even much larger) than maximum memory usage.

The language likely also has limitations in that some constructs are hard or impossible to express (similar to how Rust has memory safety safer, but pays for it by having problems implemented doubly-linked lists)


I just want to point out that the author of Goose has plenty of technical cred, having authored flatbuffers and lots of other cool stuff.

That's great, but it doesn't explain anything I'm seeing. I'm just commenting on the (presentation of) the project. It's entirely possible they have something awesome that just isn't presented well, or that I'm just too dense to grasp the awesomeness of what's before me. Whatever it is, I'm just saying I can't make sense of what I'm being sold.

Goose is a weird language. It uses a pile of pre-allocated datastacks, enforces lexical lifetimes for all data, and has first-class syntactic support for capped, growable, and shrinkable arrays. It also spits out a pile of C that gets all the optimization benefits of <insert C compiler of choices>.

Goose in particular excites me because I have done similar design work over the years.


Except when it's a license violation or in something that ends up having a security vulnerability.

>Except when it's a license violation or in something that ends up having a security vulnerability.

What's more secure isn't so simple. If you vendor something with a vulnerability then it wont be patched. But vendoring may also mean you took the 2% of the library you need and not the 98% which reduces the surface area for vulnerabilities. And it can cut the other way - you may update a package that was previously good and is now vulnerable (regressions, supply chain attacks).

There is a balance that must be struck, and I think LLM's strike a better balance than people do. Dependencies are a convenience with a cost and LLM's can trivially copy or re-implement things that we cant.


> But vendoring may also mean you took the 2% of the library you need and not the 98% which reduces the surface area for vulnerabilities

If you aren't using a library function you're not vulnerable to exploits in that code: unused but imported code is inert (possible usable as a gadget if you're vulnerable elsewhere, but at that point you're screwed anyways) and most compilers/runtimes completely eliminate it.

> you may update a package that was previously good and is now vulnerable (regressions, supply chain attacks)

There are better mitigations to this than not using a library.

You still completely ignore the license violations.


You might be exposing it to attackers without intending to use it.

>You still completely ignore the license violations.

The ones that you are imagining to happen? Its not a problem because you could simply observe proper licensing.

>If you aren't using a library function you're not vulnerable to exploits in that code

Not true, just because you arent calling a function doesnt mean it cant run. Read up on Log4Shell.


In my experience so far Claude has been meticulous about avoiding license violations.

My favorite namespacing syntax is ironically Clojures. module/func or fully.qualified.module/func or just func if you explicitly import the symbol. I vastly prefer shallow namespacing (module/func) most of the time.

I write Rust mostly for my day job (and it's also my preferred language on the side these days), so I usually end up explicitly importing all the symbols I actually use because module::func is just additional noise in an already pretty verbose language and is what's considered 'idiomatic'.

I don't really get the issue with :: being the separator used here. It's slightly ugly, but it's visually distinct from . for field access, which I do appreciate.


> Frankly, no company should be allowed to IPO without showing steady profit

This is directly counter to the original point of public markets at all


I started mirroring as much of the core git repos I depend on to my NAS with systemd timers to update from remote, and post-receive hooks to mirror externally if I control the repo. This reminds me that I should expand those efforts


I find this to be completely the opposite of my recent experience. The games are fast and with much better, consistent payoff than other sports such as football and soccer. Progress is far more discrete and there's basically always something happening except during inning or player changes. I agree that there are a lot of games, but that's a feature: you don't have to pay attention to every game. Because of the discrete nature of progress and the number of games you can get meaningful statistics out of a single season. I say this as a relatively young person (<30) who only loosely follows other sports.


> The games are fast and with much better, consistent payoff than other sports such as football and soccer.

Soccer is a slow burn where a game is always standing on a fragile equilibrium. Football and baseball are mainly boring because they are turn-based, with long periods of nothing happening between brief action moments.

Basketball is the only dominant US sports that matches soccer in terms of excitement and teams standing on a fragile equilibrium. Of course the NBA screws this up by stretching finals games into 7-game series, capping soccer-levels of excitement derived from winner-takes-all tournaments. It's no coincidence that NCAA tournaments manages to build up so much attention and such a dedicated following.


I just... don't agree. Every pitch in baseball is exciting and there are almost 300 thrown in an average game, even if most end up with no progress. Meanwhile I find "fragile equilibrium" games to be boring as hell to watch, there's hardly any progress being made! I don't want to watch an abstracted tug of war drawn out over 3 hours.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: