HNHacker News
TopNewBestAskShowJobs

adrusi

3,700 karma · joined May 11, 2011

[ my public key: https://keybase.io/adrusi; my proof: https://keybase.io/adrusi/sigs/AsJK2Q8-9_okvvc1HoWmt6KTGnL_SpJ34Ld6-QdP_EE ]
submissionscomments
adrusi··on Webcams aren't good enough
They announced just this at WWDC a couple weeks ago.
adrusi··on Webcams aren't good enough
Smartphone cameras are small and far better sensors than what you get in webcams. They rely on software to produce images of the quality we're used to seeing, especially with less-than-ideal lighting, but the lenses and sensor are still far better than the Logitech C920.

A webcam doesn't need the latest and greatest video hardware. Give it a camera module from a midrange 2017 smartphone and use the latest image processing tricks, and you'll blow almost any webcam on the market today.

adrusi··on Useless Use of "dd" (2015)
I always assumed that dd was preferred when writing disk images to flash media to ensure each hardware block is written to exactly once, extending the live of the device and increasing performance substantially. I never checked if that's actually a problem with general-purpose file IO, nothing stops the kernel from noticing when a pipe is connected to a block device and configuring an appropriate buffer.

status=progress is also quite handy. You can splice a "| dd status=progress |" in the middle of a pipeline to get a sense of what's happening.

adrusi··on Gov.uk drops jQuery from their front end
I think you're trying to draw too much of an analogy here. The point is just that advertising jQuery expertise on your resume today is evidence (though not especially strong evidence) that you might be someone whose skills are of diminishing relevance. Myself, I'm not convinced there's much harm in using jQuery, it's not exactly heavyweight. But if in fact fewer and fewer pages include it, then your expertise is relevant on fewer and fewer pages. It doesn't make sense to add a dependency on jQuery to satisfy a single dev's preference.

If your expertise is in low-level browser performance but you lack deep knowledge of React/etc, your skills aren't of diminishing relevance, and probably won't be for a long time.

adrusi··on Preview, the Mac app people forget about
Sometimes the application doesn't open files you drag onto its windows, and sometimes you want to select a file but not open it.
adrusi··on Preview, the Mac app people forget about
The macOS open/save dialog is almost identical to the Finder UI, what would you change about it? The reason it's helpful to be able to drag a file from somewhere else into the open/save dialog is that you often already have the file open somewhere. A common workflow: navigate to a document in finder, edit it in some app, save it, upload it to a web form. Similarly if you have a path to the file handy somewhere, you can hit ⌘⇧G and paste it.

And while I can see how reasonable people can disagree about the virtues of Mac/Windows/KDE open/save dialogs, Gnome definitely has the worst. Personally my KDE experience is limited, but of the other three I prefer macOS by a wide margin.

adrusi··on Use fzf for tmux session switching
You want to be able to disconnect and reconnect to your terminal session on the fly for any of a number of reasons:

- You're connected to a remote host and you don't want an unexpected network issue to kill your session

- You want to be able to periodically check on the status of something on a remote host but don't feel like keeping the connection open all the time

- You want to connect to the same session from different clients

- You may need to restart you graphical session and don't want that to kill your terminal session

A really simple way you could get this working is what abduco and detach do: the demon just blindly shuttles input and output between the client tty and the virtual tty that the interactive process is running in. However, when you reconnect to an existing session, you get no context, because the server doesn't know what it would need to tell the client for it to reassemble the tty state.

In order for that to be possible, the daemon would need to keep track of the terminal state internally. It's really annoying that that's necessary because now your actual terminal emulator isn't directly communicating with the process it's displaying, and you won't be able to access any features of your terminal that the daemon doesn't support.

But once you already have this background process that's keeping track of terminal state, you might as well build in other features that would require that, like window management, otherwise people who want those features will end up having yet another layer of terminal. If you don't want those features, you can pretend they're not there.

adrusi··on The Brilliance of “nil” in Objective-C
I think it's because the author thought the tags you use in tables are <tr> and <tc> (table-row and table-column) and then did a s/tc/td/g.
adrusi··on E Ink Gallery 3
No question reflective LCDs are rare, but you can look at the pebble smart watch or playdate game console for modern devices using reflective LCDs, for an idea of where that tech has gone.
adrusi··on TX-6 – Teenage Engineering
I doubt this will see much backstage use. I expect to see it used by buskers, who need portability (and sometimes the ability to pack up in seconds), and by artists who make fiddling with their equipment part of their performance. That and people who put it on their desk because they like the design.
adrusi··on Ask HN: What’s a good laptop for software development at around $2k?
Yes, I can only imagine the parent made a very unfortunate choice of wording, meaning "integrated" as in "integrated into the laptop," and "3d card" as "discrete graphics card." You definitely want A graphics card for battery life (not that you can buy a laptop without one) and you want it to be one integrated into the CPU.
adrusi··on Ask HN: What’s a good laptop for software development at around $2k?
I made the switch back to mac after spending the last 9 years exclusively using linux on desktop with the release of the M1 Pro chip. I haven't regretted it. Their new chips really are impressive for their combination of performance and battery life. Combine that with Apple long having been the only manufacturer to manage high display resolutions without compromising battery life. It's the first laptop that I'll leave unconnected to power even when it would be convenient to connect it.

I'm definitely very keen to use Asahi once it's more stable and has support for more of the hardware though. For now I have an Arch Linux ARM VM that I keep running for some things (Haskell development on M1 is still a bit of a mess) and I can VNC into a Linux desktop over 2.5 gigabit LAN when I really yearn for my old workflows.

adrusi··on U+237C ⍼ Right Angle with Downwards Zigzag Arrow
That's like saying it's naive and irresponsible to gooutside without locking your front door when you live in a tiny remote village with 40 other people you've known for your whole life.
adrusi··on Zim – The Zsh configuration framework
Please use #!/usr/bin/env bash if you're using bash. It seems more common to have env in /usr/bin than it is to have bash in /bin. On BSD systems, bash is often in /usr/local/bin, and on macOS the user often has a more modern bash in /opt/homebrew/bin or other package manager directory.
adrusi··on Zim – The Zsh configuration framework
If you want to write portable scripts and use a reasonable interactive shell, you need to know two shells anyway. Scripts should ideally be written to only use shell features defined in POSIX, since bash isn't available on every system. It's available pretty widely, but not on e.g. Alpine Linux by default, and the version on macOS is so ancient it doesn't have features like wait -n.

Unless you're going to use rlwrap /bin/dash as your default interactive shell (please don't) you need to know both your interactive shell and standard shell if you're going to write portable scripts.

adrusi··on An Introduction to Generics
It would be up to the caller which knows the concrete type of the value getting passed as `any` to provide an interface object with a function pointer to the concrete instantiation of `Write[T]` for T=byte. If the immediate caller also doesn't know the concrete type, it would also get that from its caller. It's ultimately very fragile, since there are definitely cases where at no point in the caller chain does anyone statically know the concrete type (like if this value is pulled from a global variable with an interface type).

I think it would be terrible to include in the language because of the inconsistencies, but it is possible to make the two examples you listed as typical cases of interface->interface coercion work with generic methods, ugly as it may be.

adrusi··on An Introduction to Generics
For the case of coercing a specifically a function argument to a different interface, there is a solution that isn't stupidly inefficient, but it's impossible to support for the general case of coercing any interface value to a different interface. I expect 90% of the time a function coerces and interface value to a different interface, that value is one of its arguments, but to support that case for generic interfaces but not the other 10% would be a really ugly design. I think you'd also have issues with treating functions that coerce their arguments to generic interfaces as first class functions.

    package p1
    type S struct{}
    func (S) Identity[T any](v T) T { return v }

    package p2
    type HasIdentity[T any] interface {
     Identity(T) T
    }

    package p3
    import "p2"
    // Because parameter v might be (and in this case is) coerced into
    // p2.HasIdentity[int], this function gets a type annotation in the compiler
    // output indicating that callers should pass a p2.HasIdentity[int] interface
    // reference for v if it exists, or nil if it doesn't, as an additional
    // argument.
    func CheckIdentity(v interface{}) {
     if vi, ok := v.(p2.HasIdentity[int]); ok {
      if got := vi.Identity(0); got != 0 {
       panic(got)
      }
     }
    }

    package p4
    import (
     "p1"
     "p3"
    )
    func CheckSIdentity() {
     p3.CheckIdentity(p1.S{})
    }
adrusi··on An Introduction to Generics
Ugh yeah. The ability to check at runtime if a value satisfies an interface, combined with structural typing...

So now the static expressivity of the type system is compromised in the name of runtime introspection. Reminiscent of how when Java added generics, runtime introspection ended up totally blind to them due to erasure.

This seems like the result of not taking care to account for the possible future addition of generics when originally designing the language — it was always well understood that they’d be a likely later addition to the language. The ability to check if a value satisfies an interface at runtime doesn’t seem all that critical, although I could be missing something, I’m not a regular user of the language.

adrusi··on libmill - Go-style concurrency in C
Well it's specifically CSP using cooperative multitasking (sadly no multithreading support unlike go) and a go-like API. CSP is a lot less specific than that.
adrusi··on Things you don't need JavaScript for
I don't think knowledge of the :target pseudoclass is an especially useful filter. It's not without its uses, but it's not exactly part of the core toolbelt either.
adrusi··on Every employee who leaves Apple becomes an ‘associate’
No it doesn't. It clearly could mean that, but it literally just means the person has associated with the company. I don't know why they'd use language that could create that confusion, but it's not straightforward dishonesty.
adrusi··on How new Linux users can increase their odds of success
There is a companion argument linked in the first paragraph which lays out what desktop Linux needs to focus on to be better for beginners. The article you're responding to is giving advice to beginners who want to get value out of Linux today, given that desktop Linux has not yet managed to make itself better for beginners.

The current state of desktop Linux is that there's a category of Linux software that is suitable for beginners, which is built atop the set of features that make Linux excellent for the people who put the amount of time into learning the operating system that is appropriate for learning a professional tool. But this category of software (the GNOME and KDE desktop environments and 3rd party software intended to run inside one or the other) doesn't do much to ease the process of learning the deeper, more compelling aspects of Linux. It provides you with an interface that's recognizable to Mac and Windows users, but doesn't provide nearly as much power, and then expects you to learn Linux in all its depth to make up for that difference in capabilities.

That makes Linux great for people who just need a web browser and maybe an email client, and it makes Linux great for people who have enough background technical knowledge to learn all its depth, but leaves it vastly inferior for everyone who needs more than a Chromebook but doesn't need a professional tool. If you fall into that category today and want to use Linux anyway, you need to learn its depths, and expect that until you do, it will be worse than the OS you're coming from.

If we want to improve the situation, we need either go all the way and make GNOME just as powerful as macOS (which is a fools errand), or make GNOME better integrated into what Linux is already great at and ease the transition.

adrusi··on The fish shell is amazing
You can get reasonable version control integration from zsh without any kind of wild oh-my-zsh config. Most distributed versions of zsh are compiled with vcs_info enabled.

    autoload -Uz vcs_info
    zstyle ':vcs_info:*' enable git hg
    zstyle ':vcs_info:*' check-for-changes true
    zstyle ':vcs_info:git*' formats "%{$fg[cyan]%}(%{$fg[green]%}%s %{$fg[blue]%}%r%{$fg[cyan]%}:%{$fg[green]%}%b%{$fg[yellow]%}%m%u%c%{$fg[cyan]%})%{$reset_color%} "

    setopt prompt_subst
    export PROMPT="%{$fg_bold[red]%}%n%{$reset_color$fg[white]%}@%{$fg_bold[green]%}%m%{$reset_color$fg[white]%}:%{$fg[cyan]%}%1~ \${vcs_info_msg_0_}%{$fg_bold[white]%}%(#.#.\$) %{$reset_color%}"
adrusi··on The fish shell is amazing
That's annoying when you have complex quoting in the pasted script, but you can always do

    bash
    PASTE_HERE
    exit
Works for everything unless the pasted commands set variables you want to use.
adrusi··on Apple October Event [video]
The pop-up cameras proved reliable and I used a OnePlus 7 Pro for two years, and found it adequately water resistant (good enough for me to give it a rinse in the sink every now and then).

The internal space that the module occupied was the only real disadvantage of the pop-up camera, restricting the space available for the battery. Although I didn't have any complaints about the battery life of this phone.

adrusi··on Serialization-Based Undo
If photo editors have an internal representation of all operations in the history of the document and the ability to recompute them all up the a given point, and they DON'T expose this to the user except through the undo button, that's a pretty big failure of design.
adrusi··on Understanding Python through its builtins
So I don't recall what size of chunks Clojure's implementation uses, but I'll assume it uses 64-bit indices with 16-word chunks, because I want to use numbers.

    (loop [i 0]
      (println (get my-vector i))
      (recur (inc i)))
Assuming no part of my-vector is cached at first, the first iteration needs to make a full 16 round trips to main memory — quite bad. But on the next iteration, all of that is cached, and we don't hit main memory at all, and the same until i=16, which requires one round trip. Then when i=16², we need to hit main memory twice, etc.

No doubt this is quite a bit worse than having everything nicely laid out sequentially in memory, but it's not as bad as you're describing.

Of course, all of that is not that material to begin with given that most elements will be pointers to begin with

I guess this is sort of true. If you're doing random lookups, then using a persistent vector instead of an array list mean 17 trips to main memory instead of just 1, so it's not totally inconsequential.

But I think (hope?) that modern JVMs can optimize collections of small immutable objects so that they're not represented as pointers to the heap. Surely ArrayList<Integer> x gets represented as int x[], and not int *x[], at least with the most optimizing JIT level.

adrusi··on Understanding Python through its builtins
Random access into a clojure vector is going to need more memory lookups than conventional sequential buffer array (I don't recall the constants used in the implementation, I think it's either 4 or 8 lookups).

But when you're indexing into the vector sequentially, the memory layout plays rather well with memory caching behavior, and most lookups are going to be in L1 cache, just like they would be in a conventional array.

So lookups are a bit more expensive, but not as much more expensive as one might imagine.

adrusi··on Twitch is hacked, and its source code leaked
EC2, Amazon's cash cow, competes with nearly identical offerings from Microsoft and Google, and is not a place where additional features are often all that valuable to customers. Any sort of breach like this on EC2 would seriously hurt Amazon's bottom line and they know it.
adrusi··on Tox: Decentralized and Encrypted Instant Messaging
Well this is free software, but u less you're competent to audit it yourself, it's still unwise to rely on its security promises. But for people who don't need the guarantees, it would be nice if Tox were more convenient to use.
← PreviousPage 2 of 34Next →