News for hackers. Stuff that matters.

mrgriffin

Re:Memory Safe Inline Assembly on Monday June 22, 2026 @06:11AM (#48628167)
Steelmanning this decision:

I would guess for the use-case of "I have a C project and I want to run it in Fil-C" the ability for this to be a warning + run-time panic is very helpful for quickly getting started. Reminds me of GHC's -fdefer-type-errors.

I agree that I wouldn't want to deploy a program where those panics are reachable*, but it's still handy for local development and/or maybe the developer knows they aren't reachable.

I haven't checked, but I'd guess there's a warning and a -Werror -style flag to opt-in to having a hard error for unsafe assembly?

* Obviously a panic is better than not. But guaranteed safeness is better than either of those.

Re:Mitigating the Billion Dollar Mistake on Monday January 12, 2026 @05:37AM (#46586606)
I'm sure Bill understands what I'm about to say, but as a person on team "require explicit initializations" I think the mitigations I would be looking at are:

1. Only require that the programmer prove the variable is initialized before it's read. Riffing on Bill's example:

    Object *x; // Fine
    if (is_foo) {
      x = &foo;
    } else {
      x = &bar;
    }
    x->a // Fine, was initialized by the time it was used.
Of course this is still a trade-off, your compiler has to work harder to prove that all paths that flow to each use are definitely-initialized. When you have initialization functions you now need to have type specifiers like 'in', 'out', and 'in/out' so that 'out' can take a pointer to uninitialized data, or something like MaybeUninit. This handles this example from Bill:

    Foo f;
    Bar b;
    grab_data(&f, &b); // Fine if 'grab_data(out Foo *, out Bar *)'.
2. Something like Rust's MaybeUninit to explicitly opt-in to wanting to deal with possibly-uninitialized data. Obviously also a trade-off, especially if you want to force all the maybe uninitialized stuff to be in an 'unsafe' block.
Re:Stackful Coroutine Made Fast on Tuesday October 28, 2025 @12:40PM (#45735158)
Making all registers caller-saved around context switches is a neat insight, it's intuitive how that could potentially lead to needing fewer instructions to execute when switching contexts.

I haven't yet digested exactly how the stacks are made to work. I think fig 8 should be obvious, but I'm getting stuck on picturing how the system guarantees that frame 1 can't grow into frame 2.

EDIT: Ah, I think I understand. It seems that they're taking advantage of a large virtual address space to give each stack loads of space, rather than them being contiguous like I assumed from fig 8.

> As modern 64-bit address-space is big enough for the allocation of many large continuous stacks [...]

> `foo :: Semigroup a, Traversable t => t a -> a` I already know that whatever is passed to this function can be traversed and have it's sum computed. It's impossible to pass something which doesn't satisfy both of those constraints as this is a specification given at the type level which is checked at compile-time.

To add to your point, I don't think foo can even be implemented (more accurately: is not total) because neither `Semigroup a` or `Traversable t` guarantee a way to get an `a`.

I think you'd need either `Monoid a` which has `mempty`, or `(Foldable1 t, Traversable t)` which guarantees that there's at least one `a` available.

Re:Detecting if an expression is constant in C on Wednesday April 23, 2025 @04:06AM (#43769709)
Would you expect IS_CONST to evaluate to the constant? With a name like that I would expect it to evaluate to true/false.

C here is asserting that the value inside is a constant and then evaluating to that constant.

Re:Accessing a DRM Framebuffer to display an image on Sunday December 08, 2024 @03:52AM (#42355921)
> One very frustration aspect is that there is basically no real documentation

I looked at DRM/KMS briefly earlier in the year and this is what made me abandon it in the end. Can you recommend any sources of information?

The atomic API and "test only commit" both sound really useful.

Re:Union types ('enum types') would be complicated in Go on Saturday December 07, 2024 @04:00AM (#42348345)
> doesn't run against the grain of the entire language

Not an expert, but my gut says maybe it runs against zero values? As in, "what's the zero value for a non-nullable reference?" Maybe the answer is something like "you can only use this type for parameters", but that seems very limiting.

Re:Localisation is too hard for Gmail on Wednesday October 21, 2020 @12:11PM (#24849191)
I think the person you're responding to is agreeing with you that you should optimize for languages other than English rather than for people naming a label "Bin" and then switching to the UK locale.
Re:A word for a value between 0 and 1 (inclusive) on Friday September 04, 2020 @06:38AM (#24373703)
FWIW, that's not dependent typing, because the type doesn't depend on run-time values. A bool is either true or false, a [0...1] is either 0 or, ..., or 1.

As for which languages allow it. I'm not sure for floats, but Pascal let you do it for ints for sure. https://wiki.freepascal.org/subrange_types

Re:Fast Fibonacci numbers using Monoids on Thursday April 23, 2020 @04:32PM (#22960969)
Please write a blog post!
I'd probably find the name Natural Seitan misleading (i.e. mistakenly buy it thinking it was vegan), but calling it "Animal Seitan" would be perfectly acceptable/clear to me .
Re:Why I’m Leaving Elm on Thursday April 09, 2020 @04:55PM (#22827089)
Forbid "\t* *\t"?
Re:Why I’m Leaving Elm on Thursday April 09, 2020 @02:14PM (#22825525)
I wouldn't do it, but this works perfectly fine. The rule is "use tabs to indent blocks of code, use spaces to align within those blocks".

  <TAB><TAB>function name(arg1, arg2,
  <TAB><TAB>              arg3)
Re:Why we need a book about naming on Thursday February 13, 2020 @05:45AM (#22316714)
What about implementing something like map for lists? You know literally nothing about the values and the function except for their types.

    map :: (a -> b) -> [a] -> [b]
    map f [] = []
    map f (a:as) = f a : map f as
Personally I don't see any reason to use longer names than f, a, and as because you can't add any additional information.

You might say "well I don't write code like that", and I don't have any answer for you. But I find I write a fair amount of generic code.

Re:All Programming Languages are Wrong (2018) on Wednesday February 12, 2020 @12:44PM (#22310865)
I'd probably think of Bool as being isomorphic to Maybe (), which would mean your map implementation looks a bit like:

    map :: Bool -> (() -> b) -> Maybe b
    map True f = Just (f ())
    map False _ = Nothing
Or, in Haskell because you've got laziness you could go with:

    map :: Bool -> b -> Maybe b
Which already exists as a combination of Control.Monad.guard and Data.Functor.(<$).

    map tf b = b <$ guard tf
Re:API Practices If You Hate Your Customers on Thursday December 12, 2019 @05:20AM (#21770763)
I've gotta say, if I was a third party to the exchange that involved your suggested message I would think the senior developer was a pompous and condescending ass. In the UK we (or at least I) wouldn't consider what you wrote to be a polite response.
Re:How to play with people who are better than you on Wednesday December 04, 2019 @10:49AM (#21703161)
I had meant to restrict my weight lifting comments to the kind of weight lifting that goes on in gyms (what was being discussed upthread). And I have to confess I don't know much about those sports you named, but do the participants really interact with each other like they would in, say basketball or soccer? Maybe there really is a rule like "there are a finite number of weights, and each can be lifted by at most one person", which would be pretty similar to "there's only one ball, therefore only the player with the ball can score"? And therefore being paired with someone who vastly outclasses you wrt lifting weights will effectively render you unable to participate (by taking all the weights you can lift, similar to taking 100% of the possessions of the ball).
Re:The most copied StackOverflow snippet of all time is flawed on Wednesday December 04, 2019 @08:36AM (#21702007)
Don't many QuickCheck-inspired libraries have special cases to ensure they generate common numbers like those? I could be misremembering, but I would have sworn I read that in the documentation of the last library I looked at (whose name escapes me).
Re:How to play with people who are better than you on Wednesday December 04, 2019 @07:03AM (#21701463)
That isn't a very good comparison. Lifting weights isn't a competition in the way that basketball is. I want to say the latter is more "zero-sum", but I'm not sure if that's correct terminology.
Re:How an Optimizing Compiler Works on Tuesday November 12, 2019 @04:58AM (#21512910)
From the article:

> multiplied does not: it starts off 0, and every time it is multiplied via multiplied = multiplied * count it remains 0.

The article then goes on to use that fact for some optimizations.

Re:Parse, Don’t Validate on Friday November 08, 2019 @12:09PM (#21484261)
You might be right, it's been a long time for me too. But if it can define new classes, then I'd expect that the code for those classes' methods would also be in the pickled format, at which point there's no particular reason you couldn't deserialize it in Haskell too... with some caveats about either needing to know what types those functions should have, or needing to build a run-time representation of those types so that they can be checked when called, or (hopefully!) crashing if you're okay with just unsafeCoercing things around.
Re:Parse, Don’t Validate on Friday November 08, 2019 @09:06AM (#21482202)
I'm pretty confident that you could write something that was equivalent to all the useful `pickle` calls. By that I mean you'll need to know which operations you'll want to do on your unpickled object:

  readAny :: forall c r. [TypeWithReadAnd c] -> String -> (forall a. c a => a -> r) -> Maybe r
  readAny types string handle 
I think it's fair to say "hey, pickle doesn't require me to list all my types explicitly", but on the other hand, it's not like pickle can conjure those types out of thin air--it considers only the types that are defined in your program.

Here's an example that uses Read as the serialization format and only deals with Int, Char and String; but hopefully you can imagine that I could replace the use of read with a per-type function that deserializes from a byte string or whatever.

https://repl.it/@mrgriffin/unpickle

Re:Parse, Don’t Validate on Friday November 08, 2019 @07:57AM (#21481775)
I think (but cannot guarantee) there's nothing much stopping you writing template Haskell to construct valid values at compile time if you want. It's just that most of the time you're (or at least I am) happy to use "unsafe" functions because the verification is simple enough to do in your head, and the other 99% of the time I'm creating values it's from run-time data.
Not to sound like a pedant, but the small spelling mistakes would scare me away if I were a potential customer.

> but even the most beautiful code is useless if it takes to long to write!

"too long"

> Tansparent

"transparent"

> visualiase

"visualize"

There are probably others, I only skimmed.

Anyway, the visualization of connecting inputs to outputs is pretty cool and I hope that it's intuitive enough to bring simple programming to more people.

I don't write brackets where the condition and body fit on one line, and do otherwise. e.g. like these:

  if (ptr == NULL) return NULL;
  for (int i = 0; i < n; ++i) dst[i] = src[i];
I particularly like it for guards at the beginning of a function, because they end up being less visually heavy, thus drawing my attention to the (presumably more business-logic-y) other lines of code.

It's somewhat like how Ruby lets you write your control structure at the end of a statement to have it only apply to that statement, e.g.

  return nil if ptr.nil?
And I find this style looks different enough to multiple statement control structures that I don't make the mistake of adding an additional statement without also adding brackets.

Of course this is a comment about formatting code, so YMMV.

Re:Dependent Haskell Is the Future (2018) on Friday August 16, 2019 @11:48AM (#20716353)
One solution to ensuring that the order is preserved (that I've actually used in production Haskell code where this was a real risk) is to use a heterogeneous list instead of a Vec.

  rzipWith :: (forall a. f a -> g a -> h a) -> Rec f as -> Rec g as -> Rec h as
With this type I don't think you'd be able to rearrange the elements, but you do have to pay the cost of using Const everywhere, as in you can specialize approximately my function as follows (handwavy, won't compile):

  zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
  zipWith f as bs = recToVec (rzipWith f' as' bs') where
    as' = vecToRec (fmap Const as)
    bs' = vecToRec (fmap Const bs)
    f' (Const a) (Const b) = Const (f a b)

  vecToRec :: Vec n (f a) -> Rec f (Replicate n a)
  recToVec :: Rec (Const a) as -> Vec (Length as) a
Rec is defined in Vinyl: https://hackage.haskell.org/package/vinyl-0.11.0/docs/Data-V...
Re:Dependent Haskell Is the Future (2018) on Friday August 16, 2019 @04:55AM (#20713320)
> there are equally disastrous bugs caused by intent - i.e. the programmer had no idea the code could fail.

At least some of these sorts of bugs (depending on how you define "fail") are captured even in Haskell today by things like Maybe. In fact, if Haskell was total (like Idris) you wouldn't even be able to write a function that searches a list for an element with this type:

    find :: (a -> Bool) -> [a] -> a
Because there's no way for you to magic an a out of nowhere in the empty list case (whereas laziness lets you use bottom). You could however write a buggy find over known non-empty lists because you could always return one of the known elements, types aren't a panacea.

Dependent types go further and let you guarantee things like "zip only compiles for two lists of exactly the same length" which can be helpful in some circumstances (specifically in Haskell we use things like zip [0..] too often to want to change the function literally called zip, but you could imagine another name, perhaps zipExact as in the Safe library).

I suspect you probably already know this and meant a different kind of failure, such as mathematically invalid (which you could probably encode via a sufficiently powerful type system), or a simple misunderstanding of the requirements (which you—as the misunderstander—obviously can't).

Re:An Open Letter to the Go Team About Try on Wednesday July 03, 2019 @02:53AM (#20342182)
I hope it's not literally to prevent people reinventing these simple data structures.

The ecosystem exerts a lot of pressure on developers to not reinvent fundamental things, in Haskell I practically never reach for a StrictTuple or StrictEither even when I'd like strictness specifically because they are clunkier and less well integrated with other libraries.

Scala is the only language that comes to mind with this issue (scalaz vs Cats) and my impression is that even they have mostly converged.

I would say Go has much stronger idioms than either of these languages, and wouldn't need to be afraid of people inventing their own fundamental types provided they're included in the standard library.

Re:Magical, Mystical JavaScript Transducers on Saturday June 29, 2019 @11:16AM (#20313035)
As a professional Haskeller who solves numerical computation problems I wouldn't call ST an escape hatch. You're right that I can't think of a "pure" way to compute a histogram, but I doubt anyone uses Haskell specifically to prevent all mutations but rather to carefully control where mutation can occur[1]. I'd wager referential transparency is "good enough purity" for almost all tastes.

[1] Of course we have plenty of other reasons to use it, but I digress.

Re:Type inference has usability problems on Friday June 28, 2019 @10:23AM (#20304559)
Not OP, but my understanding is that it's a common approach in Idris. Here's the creator of the language deriving the implementation of zipWith without writing any code: https://www.youtube.com/watch?v=X36ye-1x_HQ&t=1274

Some other examples include:

- Haskell: https://hackage.haskell.org/package/ghc-justdoit

- Scala: https://github.com/TypeChecked/alphabet-soup

- Agda: https://youtu.be/3U3lV5VPmOU?t=3159

I was under the impression that justDoIt comes from Scala, but I can't find a reference for that.

Older »