I don't understand comptime string formatting


// match - match substrings based on an expression
pub fn match(
    comptime expression: []const u8,
    source: []const u8,
) MatchIterator(expression) {
    return MatchIterator(expression).init(source);
// not accept var  
    const allocRegex = std.heap.page_allocator;
    const xx = std.fmt.allocPrint(allocRegex,"[A-Z]{1}[a-zA-Z0-9]{{1,{d}}}",.{buf.len}) catch unreachable;
    std.debug.print("test:{} \r\n",.{match(xx,buf)});

My problem is that I have functions that construct the constant (rule) so I can’t.
the match function imposes a const xx =“[A-Z]{1}[a-zA-Z0-9]{1,5}”


const xx = comptime std.fmt.allocPrint(allocRegex,"[A-Z]{1}[a-zA-Z0-9]{{1,{d}}}",.{buf.len}) catch unreachable;

The xx string is allocated with the page_allocator so it is runtime value. You cannot pass it as a comptime parameter. If you want to construct strings at comptime, take a look at std.fmt.comptimePrint.


Following @permutationlock’s advice, here’s an example:

const std = @import("std");

pub fn main() !void {
    const number: usize = 42;
    const string: []const u8 = std.fmt.comptimePrint("Number: {d}", .{ number });
    std.debug.print("{s}\n", .{ string });

And here’s something closer to what you’re trying to do:

const expression = std.fmt.comptimePrint("[A-Z]{{1}}[a-zA-Z0-9]{{1,{d}}}", .{3});

var itr = Fluent.match(expression, "Aa12");

while (itr.next()) |s| {
    std.debug.print("{s}\n", .{ s });

Note that the {{}} is a single escaped set of brackets.

fn testz( w:  usize, s :usize,vbuf : [] const u8) void {
    const ncar: usize =  w + s ;
    const regex = std.fmt.comptimePrint("^[A-Z]{{1}}[a-zA-Z0-9]{s}1,{d}{s}", .{"{", ncar,"}" });
    std.debug.print("fluent:{s} \r\n",.{regex});
    std.debug.print("fluent:{s} {} \r\n",.{vbuf,isMatch(vbuf,regex  )});


"It forces me to hardcode the value ‘ncar’ otherwise it doesn’t work.

In my form testing, I have areas under construction that may change over time.
With the C regex, I can pass a variable regex.
I understand that ‘comptime’ is a protection."

const FREGEX = struct {
    width: usize,
    scal: usize,
    ncar: usize,
    regex: []const u8, // regex control

fn testx(comptime w: usize, comptime s: usize, vbuf: []const u8) void {
    var f: FREGEX = undefined;
    f.width = w;
    f.scal = s;
    // Calculating ncar dynamically
    f.ncar = w + s;
    // Constructing the regex pattern with dynamic values
    f.regex = @as(const []u8, std.fmt.comptimePrint("^[A-Z]{{1}}[a-zA-Z0-9]{s}1,{d}{s}", .{"{", f.ncar, "}" }));
    // Printing the constructed regex pattern for debugging
    std.debug.print("fluent:{s}\n", .{f.regex});
    // Matching the input buffer with the constructed regex pattern
    std.debug.print("fluent:{s} {}\n", .{vbuf, isMatch(vbuf, f.regex)});


if I have 80 zones or more, it becomes complex and difficult to create a code generator.


In Zig, std.fmt.comptimePrint only accepts fixed values and not variables. For instance, it will accept a fixed number like 5, but it won’t accept a variable like varX.

Any computation happening at comptime needs to be done with comptime known values. If you change your code above to use comptime var f: FREGEX = undefined; then it should be fine.


I think it’s important to point out one more thing here - runtime and comptime are not fundamentally the same thing.

In Fluent, the regex trees are created without using an allocator, have @sizeOf == 0 and can be easily optimized. Each regex expression generates a custom type.

This is useful for tasks that have fixed boundaries (like building ML Tokenizers, extracting digits from strings, cleaning text, etc). Meanwhile, there are other tasks that are more suited towards runtime.

Again, @permutationlock is correct, but @JPL, I recommend that you study comptime for a bit to become familiar with exactly what it is and how it works. It will help clarify the whole design and intention of comptime-regex expressions.


I have not read or used Fluent and was responding to the immediate question posed without context. Definitely listen to Andrew on all things Fluent!

1 Like

Haha, well I’d still recommend people listen to you either way. Your points were right on both accounts.