What is this .@"some_string" syntax?

When exploring “zls” source code for learning purpose.

I encounter the .@“some_string” syntax but unable to search for it any where in the docs or with google.

fn testOrganizeImports(before: []const u8, after: []const u8) !void {
    try testDiagnostic(before, after, .{ .filter_kind = .@"source.organizeImports" });
}

Can anyone please give me some pointers.

Tks for your time!

Language Reference - Identifiers:

Identifiers must start with an alphabetic character or underscore and may be followed by any number of alphanumeric characters or underscores. They must not overlap with any keywords. See Keyword Reference.

If a name that does not fit these requirements is needed, such as for linking with external libraries, the @"" syntax may be used.

So source.organizeImports is the identifier, but because it contains a dot it must be written with the @"" syntax.

8 Likes

The @"something" syntax is mostly commonly used when the name of a field matches that of a keyword in the language. std.builtin.Type, for example, has quite a few:

switch (@typeInfo(T)) {
    .@"struct", .@"fn", .@"union", .@"enum", .@"opaque" => { 
        // these are key word 
    },
    .array, .pointer, .comptime_int, .int, .float, .error_set => {
       /// these are not
    },
}

Enum names with white-spaces are useful in situations where you need human-readable text. The best example is HTTP status codes:

enum {
    // ...
    @"I'm a teapot" = 418,
    @"Enhance Your Calm" = 420, 
    // ...
};

When constructing the response header, you just need to do a @tagName(status) to obtain the necessary text. No messing with look-up tables.

Special field names (that require the use of `@“…”) are sometimes used to denote fields with special significance. I’ve seen people do this:

const SomeStruct = struct {
    name: []const u8,
    comptime @"meta(name)": Metadata = .{ ... },

    age: [] u32,
    comptime @"meta(age)": Metadata = .{ ... },

    // ...etc
};

Another potential use is the caching of complex results:

const DataPoint = struct {
    a: f64,
    b: f64,
    @"@sin(a) + @sqrt(b) + 0.88": f64,
};

Here there’s really no good name for the field in this case. The actual expression best conveys what it is.

7 Likes

You can also use unicode symbols

const std = @import("std");
fn @"÷"(comptime T:type, a:T, b:T) T {
    return a/b;
}

fn @"²"(comptime T:type, a:T) T {
    return a*a;
}

pub fn main() !void {
    std.debug.print("{d}\n", .{@"÷"(f32, 10, 2)});
    std.debug.print("{d}\n", .{@"²"(i32, 7)});
}
9 Likes

Wow! Tks for your detailed explanation and example usecases.

That helps tremendously.

In theory, that enables programming in languages other than English:


fn @"停止並著火"() noreturn {
    // ...
}

fn @"Shaka, when the walls fell"() noreturn {
    // ...
}
3 Likes

Not sure if it should be mentioned here, but I think the linked docs entry should include some example usecase like mentioned by @chung-leong answer as it helps clarify and demonstrate good usecases.

And by next time I search for '.@" ’ in the docs I would be able to find that entry.

1 Like

Imagine all the bad / misleading things you could do with Unicode symbols… Functions named with pure whitespace? Functions named with characters that are not really what you think they are (such as I, the Turkish dotless i). The sky is the limit!

2 Likes

A surprising number of languages let you overload operators with unicode :anguished:

2 Likes

Using two different encodings of the same grapheme cluster as names for different functions, so that if somebody applies normalization the meaning of the program changes :wink:

2 Likes

You can make all functions and variables @“I am Groot”, differentiated only by the number of ZWNBSPs within their names.

8 Likes

I guess Racket (as a lisp) doesn’t really have operators (unless the module #lang implements a different syntax that has operators), but in racket you can use almost anything as an identifier. (But people tend to use it sparingly)

In Racket |something| is the identifier something so it is similar to @""
But you even can use | as identifier by escaping it with \|

Example
#lang racket

(define (x² x) 
  (* x x))

(define (x³ x) 
  (* x x x))

(module+ main
  (define || 123)
  (define |you can write almost anything in here| 'this-is-an-interned-symbol)
  (define \| 'single-vertical-bar-as-identifier)
  (define identifier\(\)with-parens "()")
  (define | | 'a-single-tab)
  (define ←→ 'left-right)
  (define ☑ "☑")
  (define 💩"💩")
  (define ∅ (set))

  (displayln ||)
  (displayln |you can write almost anything in here|)
  (displayln \|)
  (displayln identifier\(\)with-parens)
  (displayln | |)
  (displayln ←→)
  (displayln ☑)
  (displayln 💩)
  (displayln (set-empty? ∅))
  (displayln (x² 2))
  (displayln (x³ 2)))

Output:

123
this-is-an-interned-symbol
single-vertical-bar-as-identifier
()
a-single-tab
left-right
☑
💩
#t
4
8
2 Likes