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

Lots of bad advice. Using unsigned for normal integers when you know they will be positive does worse for optimization, not better. Also for (;;) {} is convention because older compilers would give warnings with while (1)

I stopped reading there.


kill Unicode. Done with this after these 25 byte single characters.

I wish I could find the pull request associated with that issue.

Tried it and realized it was gimped compared to the Linux tools it was trying to emulate. Monopolies will always be playing catchup with basic functionalities people have done for free because they make sense.

printing is never the appropriate tool. You can make your debugger print something when that line of code is reached anyway and automatically continue if you want. So what's the point of pritntf? It's just less information and features.

Let me enumerate. Printf survives debugger restarts, shows up in git diff, usually messes less with the timing, can be exchanged with coworkers or deployed to users and be toggled with logging rules, has the full power of the programming language, the output is easier to run "diff" on to compare runs, works in CI containers, has no problems with mixed language environments...

As far as I'm concerned, breakpoints and backtraces, especially of crashes, are the superpower of debuggers. Where they are not immediately applicable, I usually don't bother.


Nah.

Print debugging optimizes for timing detail and fidelity.

Debuggers optimize for data detail, at the expense of timing detail and fidelity.

In my opinion - timing & order of events is actually more meaningful.

I often don't need the extra data detail, and the debugger is going to change timing in meaningful ways.

Both are skills - both have their place. Know when logs are useful, know when debuggers are useful. Don't get stuck in the fallacy of "The one true way!" - that's the only thing I can promise is bullshit.

If you've never debugged a problem that goes away when a debugger is attached - you're woefully unprepared to have this conversation (It's much rarer, but I can even talk about times where adding a single print line was enough to change timing and make the issue harder to reproduce).

At the very least - with prints you get a tangible record of the order of operations during a reproduction. It doesn't go away, I don't have to remember how many times I've hit continue, I don't have to worry about whether pausing at this breakpoint is changing the world (and it is, because other things keep chugging - the network doesn't give a fuck that you're paused at a break point).


I’m a huge advocate for using debuggers, but saying never print is too dogmatic, and sometimes incorrect. There are plenty of environments where a debugger is not available or very difficult to setup - GPU shaders historically, embedded environments on small/custom hardware, experimental languages, etc.. Printing is both very easy, and often good enough. You should probably reach for a debugger if you keep adding prints and recompiling or if you don’t fix your bug in a couple of minutes. But aside from that, print debugging is useful and has its place, even on occasions when a good debugger is available. Never say never.

I haven't touched GPU programming in ... uh ... decades, but is print debugging readily available for shaders? That was surprising, but glad to hear it! :)

Good point, it’s getting better, but often print statement debugging is not available in shaders either, and you have to resort to the visual form of print debugging: outputting a tinted color. Crude, but often enough it’s plenty effective. Personally, I mentally put shader tint debugging in the same category as CPU print debugging.

I'm firmly in the "use a debugger" camp, but printf is sometimes indispensable when attempting to debug race conditions. By confirming timing invariants hold with printf, you can usually narrow in fairly quickly on the problem. Doing the same in a debugger is much more of a hassle. It's not impossible, certainly, but it's way more of a pain in the ass.

printing should definitely be the tool of last resort.

No one can argue how many keystrokes and brain cycles it saves using a debugger vs going through the task printing every variable.


Not this article again. His opinions on include files don't make sense anymore. Modern compilers keep track of what includes are necessary to reprocess.


What the hell do the antitrust people in the US do? Google should have been chopped to bits a decade ago and Microsoft buying Github is just nonsense. Way too much potential for abuse all around.


Nothing apparently. We've stopped caring. If it's not about getting rich right now in this lifetime then it's not worth doing. I'm also convinced governments have realised monopolies are good for them. You don't need a big government if you control the few massive corporations everyone has to use.


You're giving the government too much credit. They're not even that competent at malice. It's the large companies that control it by lobbying, not the other way around.


They're not acting like idiots though?

And they're trying to raise awareness that Microsoft helps Israel surveil and attack Palestinians, not raise awareness that there is a war going on.

Your comment is a typical one that protests should be less disruptive, but only disruptive protests have historically been effective.


But how does raising awareness help anything in this case? In the current political climate, companies are likely more afraid of presidential punishment for not supporting Israel than of any public disapproval for supporting Israel.


> Raw or multiline strings are spelled like this:

    const still_raw =
        \\const raw =
        \\    \\Roses are red
        \\    \\  Violets are blue,
        \\    \\Sugar is sweet
        \\    \\  And so are you.
        \\    \\
        \\;
        \\
    ;
This syntax seems fairly insane to me.


Maybe if you've never tried formatting a traditional multiline string (e.g. in Python, C++ or Rust) before.

If it isn't obvious, the problem is that you can't indent them properly because the indentation becomes part of the string itself.

Some languages have magical "removed the indent" modes for strings (e.g. YAML) but they generally suck and just add confusion. This syntax is quite clear (at least with respect to indentation; not sure about the trailing newline - where does the string end exactly?).


C and Python automatically concatenate string literals, and Rust has the concat! macro. There's no problem just writing it in a way that works correctly with any indentation. No need for weird-strings.

  " one\n"
  "  two\n"
  "   three\n"


Personally, I'd rather prefix with `\\` than have to postfix with `\n`. The `\\` is automatically prepended when I enter a newline in my editor after I start a multiline string, much like editors have done for C-style multiline comments for years.

Snippet from my shader compiler tests (the `\` vs `/` in the paths in params and output is intentional, when compiled it will generate escape errors so I'm prodded to make everything `/`):

    test "shader_root_gen" {
        const expected =
            \\// Generated file!
            \\
            \\pub const @"spriteszzz" = opaque {
            \\    pub const @"quadsprite" = @import("src\spriteszzz/quadsprite.glsl");
            \\};
            \\
            \\pub const @"sprites" = opaque {
            \\    pub const @"universalsprite" = @import("src\sprites/universalsprite.glsl");
            \\};
            \\
            \\pub const @"simpleshader" = @import("src/simpleshader.glsl");
            \\
        ;

        const cmdline =
            \\--prefix src -o testfile.zig src\spriteszzz/quadsprite.glsl src\sprites/universalsprite.glsl src/simpleshader.glsl
        ;

        var args_iter = std.mem.tokenizeScalar(u8, cmdline, ' ');
        const params = try Params.parseFromCmdLineArgs(&args_iter);

        var buffer: [expected.len * 2]u8 = undefined;
        var stream = std.io.fixedBufferStream(buffer[0..]);
        try generateSource(stream.writer().any(), params.input_files.items, params.prefix);
        const actual = stream.getWritten();

        try std.testing.expectEqualSlices(u8, expected, actual);
    }


I may be missing something but come Go has a simple:

    `A
       simple
          formatted
             string
    `

?


Yours is rendered as:

A\n\tsimple\n\t\tformatted\n\t\t\tstring\n\t

If you wanted it without the additional indentation, you’d need to use a function to strip that out. Typescript has dedent which goes in front of the template string, for example. I guess in Zig that’s not necessary which is nice.


Okay I get it now. Formatted multiline string in code without an actual formatting and no string concat.


The problem is that usually you have something like

  fn main() {
    if something {
      print(`A
  simple
  formatted
  string`)
    }
  }
which looks ugly and confusing.


Significant whitespace is not difficult to add to a language and, for me, is vastly superior than what zig does both for strings and the unnecessary semicolon that zig imposes by _not_ using significant whitespace.

I would so much rather read and write:

    let x = """
      a
      multiline string
      example
    """
than

    let x =
      //a
      //multiline string
      //example
    ;
In this particular example, zig doesn't look that bad, but for longer strings, I find adding the // prefix onerous and makes moving strings around different contexts needlessly painful. Yes, I can automatically add them with vim commands, but I would just rather not have them at all. The trailing """ is also unnecessary in this case, but it is nice to have clear bookends. Zig by contrast lacks an opening bracket but requires a closing bracket, but the bracket it uses `;` is ambiguous in the language. If all I can see is the last line, I cannot tell that a string precedes it, whereas in my example, you can.

Here is a simple way to implement the former case: require tabs for indentation. Parse with recursive descent where the signature is

    (source: string, index: number, indent: number, env: comp_env) => ast
Multiline string parsing becomes a matter of bumping the indent parameter. Whenever the parser encounters a newline character, it checks the indentation and either skips it, or if is less than the current indentation requires a closing """ on the next line at a reduced indentation of one line.

This can be implemented in under 200 lines of pure lua with no standard library functions except string.byte and string.sub.

It is common to hear complaints about languages that have syntactically significant whitespace. I think a lot of the complaints are fair when the language does not have strict formatting rules: python and scala come to mind as examples that do badly with this. With scala, practically everyone ends up using scalafmt which slows down their build considerably because the language is way too permissive in what it allows. Yaml is another great example of significant whitespace done poorly because it is too permissive. When done strictly, I find that a language with significant whitespace will always be more compact and thus, in my opinion, more readable than one that does not use it.

I would never use zig directly because I do not like its syntax even if many people do. If I was mandated to use it, I would spend an afternoon writing a transpiler that would probably be 2-10x faster than the zig compiler for the same program so the overhead of avoiding their decisions I disagree with are negligible.

Of course from this perspective, zig offers me no value. There is nothing I can do with zig that I can't do with c so I'd prefer it as a target language. Most code does not need to be optimized, but for the small amount that does, transpiling to c gives me access to almost everything I need in llvm. If there is something I can't get from c out of llvm (which seems highly unlikely), I can transpile to llvm instead.


Does `scalafmt` really slow down builds "considerably"? I find that difficult to believe, relative to compile time.


Even if we ignore solutions other languages have come up with, it's even worse that they landed on // for the syntax given that it's apparently used the same way for real comments.


But those are two different slashes? \\ for strings and // for comments?


Yeah I agree \\ is not the best choice visually (and because it looks quite similar to //

I would have probably gone with ` or something.


> it's even worse that they landed on // for the syntax

.. it is using \\


I worked with browsers since before most people knew what a browser was and it will never cease to amaze me how often people confuse slash and backslash, / and \

It’s some sort of mental glitch that a number of people fall into and I have absolutely no idea why.


I doubt those very people would confuse the two when presented with both next to each other: / \ / \. The issue is, they're not characters used day-to-day so few people have made the association that the slash is the one going this way / and not the one going the other way \. They may not even be aware that both exist, and just pick the first slash-like symbol they see on their keyboards without looking further.


I wonder if it's dyslexia-adjacent. Dyslexic people famously have particular difficulty distinguishing rotated and reflected letterforms.


Could be. The frequency is such that it could be dyslexics. It's not all the time, but it's a steady rate of incidence.


I think in the 90's it was just people repeating a pattern they learned from Windows/DOS.

It used to grate on my nerves to hear people say, e.g. "H T T P colon backslash backslash yahoo dot com".

But I think they always typed forward slash, like they knew the correct slash to use based on the context, but somehow always spoke it in DOSish.


We can just use a crate for that and don't have to have this horrible comment like style that brings its own category of problems. https://docs.rs/indoc/latest/indoc/


And what if you do want to include two spaces at the beginning of the block (but not any of the rest of the indentation)?

Choice of specific line-start marker aside, I think this is the best solution to the indented-string problem I've seen so far.


I think Java's solution is much cleaner.


For those of us that haven't used Java for a decade...

> In text blocks, the leftmost non-whitespace character on any of the lines or the leftmost closing delimiter defines where meaningful white space begins.

From https://blogs.oracle.com/javamagazine/post/text-blocks-come-...

It's not a bad option but it does mean you can't have text where every line is indented. This isn't uncommon - e.g. think about code generation of a function body.


Why couldn't you have it?

You just put the ending """ where you want it relative to the content.


Ah I see - didn't notice it includes the trailing """. Tbh I still prefer Zig's solution. It's more obvious. (Though they should have picked a less intrusive prefix, I'd have gone with a backtick.)


Right, this is a pretty common syntax, but doesn't address the same problem as Zig's syntax.

I've only seen two that do: the Zig approach, and a postprocessing ‘dedent’ step.


Zig does not really try to appeal to window shoppers. this is one of those controversial decisions that, once you become comfortable with the language by using it, you learn to appreciate.

spoken as someone who found the syntax offensive when I first learned it.


It is not the insane syntax, but quite insane problem to solve.

Usually, representing multiline strings within another multiline string requires lots of non-trivial escaping. This is what this example is about: no escaping and no indent nursery needed in Zig.


I think Kotlin solves it quite nicely with the trimIndent. I seem to recall Golang was my fav, and Java my least, although I think Java also finally added support for a clean text block.

Makes cut 'n' paste embedded shader code, assembly, javascript so much easier to add, and more readable imo. For something like a regular expressions I really liked Golang's back tick 'raw string' syntax.

In Zig I find myself doing an @embedFile to avoid the '\\' pollution.


Visually I dislike the \\, but I see this solves the problem of multiline literals and indentation in a handy, unambiguous way. I’m not actually aware of any other language which solves this problem without a function.


It seems very reasonable and comes with several technical and cognitive advantages. I think you're just having a knee-jerk emotional reaction because it's different than what you're used to, not because it's actually bad.


I like the idea of repeating the delimiter on every line. However `//` looks like a comment to me. I could simply choose double quote:

    const still_raw =
        "const raw =
        "    "Roses are red
        "    "  Violets are blue,
        "    "Sugar is sweet
        "    "  And so are you.
        "    "
        ";
        "
    ;
This cannot be confused with a string literal because a string literal cannot contain newline feeds.


What if you have something like

    const raw =
        "He said "Hello"
        "to me
    ;
Wouldn't that be a mess to parse? How would you know that "He said " is not a string literal and that you have to continue parsing it as a multiline string? How would you distinguish an unclosed string literal from a multiline string?


My immediate thought was hmm, that's weird but pretty nice. The indentation problem indeed sucks and with a halfway decent syntax highlighter you can probably de-emphasize the `//` and make it less visually cluttered.


I think everyone has this reaction until they start using it, then it makes perfect sense, especially when using editors that have multiple cursors and can operate on selections.


I think the syntax highlighting for this could make it more readable. Make the leading `\\` a different color to the string content.


I had the exact opposite reaction.


that was my favourite bit in the entire post - the one place where zig has unambiguously one-upped other languages. the problems it is solving are:

1. from the user's point of view, you can now have multiline string literals that are properly indented based on their surrounding source code, without the leading spaces being treated as part of the string

2. from an implementation point of view having them parsed as individual lines is very elegant, it makes newline characters in the code unambiguous and context independent. they always break up tokens in the code, regardless of whether they are in a string literal or not.


When I first read it I thought it was line comments.


Upvoting because similar comments here suggest that you are not alone.

People are having trouble distinguishing between '//' and '\\'.


I really like zig but that syntax is indeed insane.


I had the same issue. I went back to the calendar and it said I got 100% of the words. So I guess it's not always possible and I spent all that time trying for no reason.


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

Search: