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

Can screen readers emit their narration as text instead of / in addition to audio?

Yes, they can. NVDA has a Speech Viewer. VoiceOver (Mac) has the caption panel.

NVDA Speech viewer: https://download.nvaccess.org/documentation/userGuide.html#S... Caption Panel: https://support.apple.com/guide/voiceover/use-the-caption-pa...


Yes. Output can be sent to a Braille device too.

The error from Rust's File::create basically only contains the errno result. So it's eg. "permission denied" vs "failed to create file: permission denied".

Python's

    f = open('foo.txt', 'w')
is even more succinct, and the exception thrown on failure will not only contain the reason, but the filename and the whole backtrace to the line where the error occurred.

But no context, so in the real world you need to write:

    try:
        f = open('foo.txt', 'w')
    except Exception as e:
        raise NecessaryContext("important information") from e
Else your callers are in for a nightmare of a time trying to figure out why an exception was thrown and what to do with it. Worse, you risk leaking implementation details that the caller comes to depend on which will also make your own life miserable in the future.

How is a stack trace with line numbers and a message for the exception it self not enough information for why an exception was thrown?

The exceptions from something like open are always pretty clear. Like, the files not found, and here is the exact line of code and the entire call stack. what else do you want to know to debug?


It's enough information if you are happy to have a fragile API, but why would you purposefully make life difficult not only for yourself, but the developers who have their code break every time you decide to change something that should only be an internal implementation detail?

Look, if you're just writing a script that doesn't care about failure — where when something goes wrong you can exit and let the end user deal with whatever the fault was, you don't have to worry about this. But Go is quite explicitly intended to be a systems language, not a scripting language. That shit doesn't fly in systems.

While you can, of course, write systems in Python, it is intended to be a scripting language, so I understand where you are coming from thinking in terms of scripts, but it doesn't exactly fit the rest of the discussion that is about systems.


That makes even less sense becasue go errors provide even less info other then a chain of messages. They might as well be lists of strings. You can maybe reassbmle a call stack your self if all of the error handlers are vigalente about wrapping

> That makes even less sense becasue go errors provide even less info other then a chain of messages.

That doesn't make sense. Go errors provide exactly whatever information is relevant to the error. The error type is an interface for good reason. The only limiting bound on the information that can be provided is by what the computer can hold at the hardware level.

> They might as well be lists of strings.

If a string is all your error is, you're doing something horribly wrong.

Or, at very least, are trying to shoehorn Go into scripting tasks, of which it is not ideally suited for. That's what Python is for! Python was decidedly intended for scripting. Different tools for different jobs.

Go was never designed to be a scripting language. But should you, for some odd reason, find a reason to use in that that capacity, you should at least being using its exception handlers (panic/recover) to find some semblance of scripting sensibility. The features are there to use.

Which does seem to be the source of your confusion. You still seem hung up on thinking that we're talking about scripting. But clearly that's not true. Like before, if we were, we'd be looking at using Go's exception handlers like a scripting language, not the patterns it uses for systems. These are very different types of software with very different needs. You cannot reasonably conflate them.


Chill with being condescending if you want a discussion.

The error type in go is literally just a string

type error interface { Error() string }

That's the whole thing.

So i dont know what your talking about then.

The wrapped error is a list of error types. Which all include a string for display. Displaying an error is how you get that information to the user.

If you implement your own error, and check it with some runtime type assertion, you have the same problem you described in python. Its a runtime check, the API your relying on in whatever library can change the error returned and your code won't work anymore. The same fragile situation you say exists in python. Now you have even less information, theres no caller info.


> The error type in go is literally just a string

No, like I said before, it's literally an interface. Hell, your next line even proves it. If it were a string, it would be defined as:

    type error string
But as you've pointed out yourself, that's not its definition at all.

> So i dont know what your talking about then.

I guess that's what happens when you don't even have a basic understanding of programming. Errors are intended to be complex types; to capture all the relevant information that pertains to the error. https://go.dev/play/p/MhQY_6eT1Ir At very least a sentinel value. If your error is just a string, you're doing something horribly wrong — or, charitably, trying to shoehorn Go into scripting tasks. But in that case you'd use Go's exception handlers, which bundles the stack trace and all alongside the string, so... However, if your workload is script in nature, why not just use Python? That's what it was designed for. Different tools for different jobs.


This guy can't help his self except to act like an ass

It is always curious when a comment on the internet is anthropomorphized. Where is the logic found in that?

They should have made the point about knowing where errors will happen.

The cherry on top is that you always have a place to add context, but it's not the main point.

In the Python example, anything can fail anywhere. Exceptions can be thrown from deep inside libraries inside libraries and there's no good way to write code that exhaustively handles errors ahead of time. Instead you get whack-a-mole at runtime.

In Go, at least you know where things will fail. It's the poor man's impl of error enumeration, but you at least have it. The error that lib.foo() returned might be the dumbest error in the world (it's the string "oops") but you know lib.foo() would error, and that's more information you have ahead of time than in Python.

In Rust or, idk, Elm, you can do something even better and unify all downstream errors into an exhaustive AGDT like RequestError = NetworkError(A | B | C) | StreamError(D | E) | ParseError(F | G) | FooError, where ABCDEFG are themselves downstream error types from underlying libraries/fns that the request function calls.

Now the callsite of `let result = request("example.com")` can have perfect foresight into all failures.


I don't disagree that exceptions in python aren't perfect and rust is probably closest of them all to getting it right (though still could be improved). I'm just saying stack traces with exceptions provide a lot of useful debugging info. IMO they're more useful then the trail of wrapped error strings in go.

exceptions vs returned errors i think is a different discussion then what im getting at here.


I disagree, adding context to errors provide exactly what is needed to debug the issue. If you don't have enough context it's your fault, and context will contain more useful info than a stack trace (like the user id which triggered the issue, or whatever is needed).

Stack traces are reserved for crashes where you didn't handle the issue properly, so you get technical info of what broke and where, but no info on what happened and why it did fail like it did.


It's one piece of information, but logging at the error location does that still. And if you have a function that's called in multiple places how do you know the path that got you into that place. If it wasn't useful we wouldn't try to recreate them with wrapped errors

You wrap errors primarily to avoid the implementation detail leak. Even where errors have stack traces, you still need to do that, as was already described earlier. What debugging advantage comes with that is merely an aded bonus (A really nice bonus, to be sure. Attaching stack traces is computationally wasteful, so it is a win to not have to include them).

You can get away with not doing that when cowboy coding scripts. Python was designed to be a scripting language, so it is understandable that in Python you don't often need to worry about it. But Go isn't a scripting language. It was quite explicitly created to be a systems language. Scripts and systems are very different types of software with very different needs and requirements. If you are stuck thinking in terms of what is appropriate for scripting, you're straight up not participating in the same thread.


> I'm just saying stack traces with exceptions provide a lot of useful debugging info.

The Go team actually did a study on exactly that; including stack traces with errors. Like you, they initially thought it would be useful (hence the study), but in the end, when the data was in, they discovered nobody ever actually used them. Meaningful errors proved to be far more useful.

Science demands replication, so if your study disagrees, let's see it. But in the absence of that, the Go study is the best we've got and it completely contradicts what you are telling us. Making random claims up on the spot based on arbitrary feelings isn't indicative of anything.

That said, I think we can all agree there is a limited place for that type of thing (although in that place you shouldn't use Go at all — there are many other languages much better suited to that type of problem space), but in that place if you had to use Go for some strange reason you'd use panic and recover which already includes the stack trace for you. The functionality is already there exactly as you desire when you do need to bend Go beyond what it is intended for.


like why did the program even choose to open this file? a stack trace is useless if your code is even a little bit generic

We were taught not to use exceptions for control flow, and reading a file which does not exist is a pretty normal thing to handle in code flow, rather than exceptions.

That simple example in Python is missing all the other stuff you have to put around it. Go would have another error check, but I get to decide, at that point in the execution, how I want to handle it in this context


In Python, it’s common to use exceptions for control flow. Even exiting a loop is done via an exception: `StopIteration`.

It's not "common". You have to deal with StopIteration only when you write an iterator with the low-level API, which is maybe once in the career time for most of developers.

isn't break more normal

The point is that the use of exceptions is built into the language, so, for example, if you write "for something in somegeneratorfunction():" then somegeneratorfunction will signal to the for loop that it is finished by raising this exception.

I’d say it’s more common for iterator-based loops to run to completion than to hit a `break` statement. The `StopIteration` exception is how the iterator signals that completion.

> the exception thrown on failure will not only contain the reason, but the filename and the whole backtrace to the line where the error occurred.

... with no other context whatsoever, so you can't glean any information about the call stack that led to the exception.

Exceptions are really a whole different kettle of fish (and in my opinion are just strictly worse than even the worst errors-as-values implementations).


Your Go example included zero information that Python wouldn't give you out-of-the-box. And FWIW, since this is "Go vs Rust vs Zig," both Rust and Zig allow for much more elegant handling than Go, while similarly forcing you to make sure your call succeeded before continuing.

And also nothing about that code tells you it can throw such an exception. How exciting! Just what I want the reason for getting woken up at 3am due to prod outage to be.

Marginal gains over AVIF.

(Also I am highly skeptical of the importance of these generation loss tests.)


Very nice in video workflows, where it's common to write out image sequences to disk.


Social media exists


That's the whole internet now. That or Anubis.


I get adding that to dynamic pages, but this is a static page.

Have we gone backwards to the point where we can’t even serve a static page now?


Or do the rational thing and rate limit GET requests to human speeds.


Based on what fingerprint?


Fingerprint: *


*distant sound of the sorcerer's apprentice is heard*


Mutable releases are used for continuous/nightly builds.


In Java with Maven these have a special suffix, "-SNAPSHOT". So "1.0.0-SNAPSHOT". Releases, like "1.0.0" are immutable once released. I always thought that was a pretty sane model.


You recoup the saving of home automation immediately as additional leisure time. But for most people, work automation neither reduces your working time nor increases your wage.


You're unlikely to get any radio signal that isn't specifically meant for you.


If SETI would be able to catch their signal on Earth, then antenna array in the space aimed at them, far from Earth to prevent our noise could work.


That's not how electromagnetic radiation works.


It kind of is. You're thinking directionality, but there's also the fact that optimal transmission will involve using compression and possibly encryption, which by its nature turns the signal into noise if you don't already know it's a signal. An optimal signal, which it seems reasonable to assume would be what aliens would be using by the time they're communicating across star systems, would be much more difficult to detect as a signal than something like an FM radio station, which puts a lot of energy into broadcasting a carrier that is there even if the station is transmitting total silence.


You're forgetting the Contact method where the actual signal is buried in a beacon signal. The beacon signal is very much a "primitive" non-random not noise signal...primes. Now that you've recorded enough of that beacon signal, someone analyses each of the pulses to realize there's a message embedded within. This way, you don't need a response to know someone go it. When they magically show up in the machine you've sent the plans as that message, you'll know the message was received.


No, I'm not forgetting fictional cases in which the point was to transmit to an unknown civilization. I'm talking about the real way that real civilizations are going to transmit data to each other, without meaning for it to be picked up randomly, on the assumption that while aliens may or may not have human-comprehensible motivations we can generally operate on the assumption that they will not be stupid and wasteful in the pursuit of their goals.

This isn't quite why I wrote this, but it's close enough: https://jerf.org/iri/post/2023/alien_communication/ If we're going to argue in the form of fiction.


We sent a gold plate with a bunch of data on it hurling through space on the off chance that a) it is ever found, b) it is found be intelligent beings, c) would figure out the little puzzles. In this case, the beacon would be the satellite itself even if its power has long since died and no longer emits any RF energy.

It's not actually sci-fi. They sent a message with Arecibo that was also encoded if not within a beacon signal. Just because it was a scifi plot does not mean its not something that could be done to good use. If humans wanted, we could send a similar beacon signal even if it's not pulses of all the primes between 1-101 with the same data from the gold plate.

At one point, flying like a bird was scifi. Traveling to the moon was scifi. Having a computer that fit in the palm of your hand was scifi. There's a lot of actual science that has been inspired from a scifi idea.


Efficient communication looks like noise.


I use an MVNO and I never needed any ID.


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

Search: