Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: New keyword seqblk instead of special syntax for labeled blocks. #4412

Closed
ghost opened this issue Feb 8, 2020 · 3 comments
Closed
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ghost
Copy link

ghost commented Feb 8, 2020

Alternative to the current syntax for labeled scopes, that would be beneficial if combined with #4285 (AConf literals).

Below are examples from the documentation written with the alternative seqblk based syntax:

test "labeled break from labeled block expression" {
   var y: i32 = 123;
    const x = seqblk blk {
	y += 1;
	break blk, y; // label and value arguments always present
    };
	// ...
}

test "nested break" {
    while (true) seqblk outer {
        while (true) {
            break outer, _ ; // allow `_` when no value is returned from the block
        }
    }
	// ...
}

test "nested continue" {
    var i: usize = 0;
    while (i < 10) : (i += 1) seqblk outer {
        while (true) {
            continue outer;
            // `continue _ ;` to continue from innermost loop
        }
    }
	// ...
}

test "while else" {
    assert(rangeHasNumber(0, 10, 5));
    assert(!rangeHasNumber(0, 10, 15));
}

fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
    var i = begin;
    return while (i < end) : (i += 1) {
        if (i == number) {
            break _, true; // `_` as first arg means break from innermost scope
        }
    } else false;
}

const success = seqblk x {
    var i: usize = 0;
    while (i < n) : (i += 1) {
        if (found(i))
            break x, true;
    }
    break x, false;
};

In combination with #4285 (AConf literals), it becomes easy to add configuration options to sequential blocks. For example .{.constantTime = true} to take a use case from #1776 .

In short:

< seqblk <blkname>? <<AConf literal> : >? > { <statement>* }

where <AConf literal> would be of the form .{ <.config=.ConfigOption>* }

The seqblk keyword would only be used when you need either a label and/or a different configuration for a scope, so in most cases code wouldn't need changing with this proposal.

seqblk blk .{.runtimeSafety = .OFF, .blocking = false} : {
// ... statements here
}

while(cond) seqblk outer { // only use label, default config
    while(cond2) seqblk .{.runtimeSafety =.OFF} : { // no label, change config
        // ...
        if(somecond){
            continue outer;
        }
    }
}
@ikskuh
Copy link
Contributor

ikskuh commented Feb 10, 2020

I really like the approach of having a break-Operator that takes one operand for "break loop" and two operands for "return value from block".

But i would remove the option for "implicit block break" with break _, … as it's even hard to recognize what will be broken in your code examples above.

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Feb 10, 2020
@andrewrk andrewrk added this to the 0.7.0 milestone Feb 10, 2020
@ghost
Copy link

ghost commented Apr 13, 2020

I kind of like this due to the same reasons as MasterQ32, but on the other hand I think the keyword seqblk would make it less readable. Simplicity is important, but as zig prioritises reading code over writing code and even though this change would (maybe) simplify writing the code, I think that the drawbacks in readability are more significant here.

@ghost
Copy link
Author

ghost commented Apr 15, 2020

I see this issue was closed, but I will leave some more comments in case this proposal is brought up again, perhaps in relation to #4285, or #4294.

Turns out that the fn keyword would work in place of seqblk in the examples above, and the comma between label and "return value" in break statements can be replaced with => which looks nicer.

pub fn main() void{
  // no parenthesis behind 'fn', so this is not a function definition or function call. 
  // it can unambiguously be determined to be a block scope
  fn label{ 
    // ...
    break label;
    // ...
  }

  const x = fn label{
    // ...
    break label => 5;
  }

  const x2 = {
    // ...
    break => 5; // no need for block label with '=>'
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

2 participants