How to mute jslint error on do{}while(false) - jslint

In this simple code:
do {
console.log('o');
} while (false);
jslint produces a warning on the last line saying Unexpected 'false'
I understand why, but I still want to mute it because in these cases that's how I want to have the control flow.

Let's look at what jslint expects in the while statement. From the source:
labeled_stmt('while', function () {
one_space();
var paren = next_token;
funct.loopage += 1;
advance('(');
step_in('control');
no_space();
edge();
this.arity = 'statement';
this.first = expected_relation(expression(0));
if (this.first.id !== 'true') {
expected_condition(this.first, 'unexpected_a');
}
no_space();
step_out(')', paren);
one_space();
this.block = block('while');
if (this.block.disrupt) {
prev_token.warn('strange_loop');
}
funct.loopage -= 1;
return this;
});
It mostly reads like English. 'while', one space, (, no space, expected expression, no space, ).
So let's look at what an expression(0) is. You can read through the source if you're really interested, but to be honest I can't really wrap my head around it either. Sorry. https://github.com/douglascrockford/JSLint/blob/master/jslint.js
As far as I can tell, though, expression(0) traverses the tree of operators and operands, and looks for values with a Right Binding Power greater than 0? And false has a binding power of 0? But variables and comparisons are okay here. I have no clue how that even works. Ask Crockford.
As for shutting up jslint, here is my suggestion:
/*jslint devel: true, continue: true */
var i = 0;
var forever = false;
do {
i = i + 1;
if (i < 5) {
continue;
}
console.log('o');
} while (forever);

Related

SwiftUI ViewBuilder: is it guaranteed that in `if/ese` statement `else` clause isn't executed when condition is true?

I ask this because I suddenly realized today that, since the if/else statement we use to build View in SwiftUI is interpreted by ViewBuilder, it may behave differently than the plain old if/else statement in Swift language. Could it be that, for some (e.g. performance) reason, SwiftUI pre-execute both clauses and cache the result? Does anyone know it for sure?
I remember I observed some confusing behavior in the past, which might be explained by this hypothesis. But unfortunately I can't recall an example.
The way a result builder transforms your code is spelled out in SE-0289: Result builders. Section “Selection statements” describes how if/else statements are transformed. It gives the following example:
Consider the following code:
if i == 0 {
"0"
} else if i == 1 {
"1"
} else {
generateFibTree(i)
}
Under this pattern, the example code becomes something like the
following:
let vMerged: PartialResult
if i == 0 {
var firstVar = "0"
var firstBlock = BuilderType.buildBlock(firstVar)
vMerged = BuilderType.buildEither(first: firstBlock)
} else if i == 1 {
var secondVar = "1"
var secondBlock = BuilderType.buildBlock(secondVar)
vMerged = BuilderType.buildEither(second:
BuilderType.buildEither(first: secondBlock))
} else {
var elseVar = generateFibTree(i)
var elseBlock = BuilderType.buildBlock(elseVar)
vMerged = BuilderType.buildEither(second:
BuilderType.buildEither(second: elseBlock))
}
You can also read a detailed description of the transformation algorithm, but I think the example makes it clear enough that it will only execute one branch of an if/else statement.

Match brackets the kotlin way

I'm giving Kotlin a go; coding contently, I have an ArrayList of chars which i want to classify depending on how brackets are matched:
(abcde) // ok characters other than brackets can go anywhere
)abcde( // ok matching the brackets 'invertedly' are ok
(({()})) // ok
)()()([] // ok
([)] // bad can't have different overlapping bracket pairs
((((( // bad all brackets need to have a match
My solution comes out(recursive):
//charList is a property
//Recursion starter'upper
private fun classifyListOfCharacters() : Boolean{
var j = 0
while (j < charList.size ) {
if (charList[j].isBracket()){
j = checkMatchingBrackets(j+1, charList[j])
}
j++
}
return j == commandList.size
}
private fun checkMatchingBrackets(i: Int, firstBracket :Char) : Int{
var j = i
while (j < charList.size ) {
if (charList[j].isBracket()){
if (charList[j].matchesBracket(firstBracket)){
return j //Matched bracket normal/inverted
}
j = checkMatchingBrackets(j+1, charList[j])
}
j++
}
return j
}
This works, but is this how you do it in Kotlin? It feels like I've coded java in Kotlin syntax
Found this Functional languages better at recursion, I've tried thinking in terms of manipulating functions and sending them down the recursion but to no avail. I'd be glad to be pointed in the right direction, code, or some pseudo-code of a possible refactoring.
(Omitted some extension methods regarding brackets, I think it's clear what they do)
Another, possibly a simpler approach to this problem is maintaining a stack of brackets while you iterate over the characters.
When you encounter another bracket:
If it matches the top of the stack, you pop the top of the stack;
If it does not match the top of the stack (or the stack is empty), you push it onto the stack.
If any brackets remain on the stack at the end, it means they are unmatched, and the answer is false. If the stack ends up empty, the answer is true.
This is correct, because a bracket at position i in a sequence can match another one at position j, only if there's no unmatched bracket of a different kind between them (at position k, i < k < j). The stack algorithm simulates exactly this logic of matching.
Basically, this algorithm could be implemented in a single for-loop:
val stack = Stack<Char>()
for (c in charList) {
if (!c.isBracket())
continue
if (stack.isNotEmpty() && c.matchesBracket(stack.peek())) {
stack.pop()
} else {
stack.push(c)
}
}
return stack.isEmpty()
I've reused your extensions c.isBracket(...) and c.matchesBracket(...). The Stack<T> is a JDK class.
This algorithm hides the recursion and the brackets nesting inside the abstraction of the brackets stack. Compare: your current approach implicitly uses the function call stack instead of the brackets stack, but the purpose is the same: it either finds a match for the top character or makes a deeper recursive call with another character on top.
Hotkey's answer (using a for loop) is great. However, you asked for an optimized recursion solution. Here is an optimized tail recursive function (Note the tailrec modifier before the function):
tailrec fun isBalanced(input: List<Char>, stack: Stack<Char>): Boolean = when {
input.isEmpty() -> stack.isEmpty()
else -> {
val c = input.first()
if (c.isBracket()) {
if (stack.isNotEmpty() && c.matchesBracket(stack.peek())) {
stack.pop()
} else {
stack.push(c)
}
}
isBalanced(input.subList(1, input.size), stack)
}
}
fun main(args: Array<String>) {
println("check: ${isBalanced("(abcde)".toList(), Stack())}")
}
This function calls itself until the input becomes empty and returns true if the stack is empty when the input becomes empty.
If we look at the decompiled Java equivalent of the generated bytecode, this recursion has been optimized to an efficient while loop by the compiler so we won't get StackOverflowException (removed Intrinsics null checks):
public static final boolean isBalanced(#NotNull String input, #NotNull Stack stack) {
while(true) {
CharSequence c = (CharSequence)input;
if(c.length() == 0) {
return stack.isEmpty();
}
char c1 = StringsKt.first((CharSequence)input);
if(isBracket(c1)) {
Collection var3 = (Collection)stack;
if(!var3.isEmpty() && matchesBracket(c1, ((Character)stack.peek()).charValue())) {
stack.pop();
} else {
stack.push(Character.valueOf(c1));
}
}
input = StringsKt.drop(input, 1);
}
}

Is it possible to define your own operators in Rascal?

I'm writing some test helper functions to make the output more sensible:
bool tstEq(first, second) {
if(first == second)
return true;
else {
println("<first> was not equal to <second>");
return false;
}
}
Is it possible to do something like this?
bool ===(first, second) = tstEq(first, second);
usage:
test bool myTest() = 1 === 2
Which would result in something like:
rascal>:test
1 was not equal to 2
bool: false
A short answer: no. I fully agree that this can be convenient (but may also lead to less readable code).
Given the large list of topics we want to address first, it is unlike that such a feature will come to Rascal in the near future.

ActionScript Haxe Evaluate a referenced variable inside a loop in a closure

I've been programming some stuff in ActionScript (Haxe) and arrived this very specific problem.
Here's the code (pseudo :S):
var func:Array = new Array(256);
(A) var i:Int = 0;
for(;i<256;i++) { // OR // for(i in 0...256) {
func[i] = function() { trace(i); }
}
func[0]();
func[127]();
func[256]();
The above code outputs (a):
256
256
256
I want that to be (b):
0
127
256
That doesn't happen, because ActionScript/Haxe is assigning the reference of i to the function, and since i equals 256 at the end of the loop where the functions get evaluated, that's why I get (a).
Does anyone know of a way to avoid that and get the expected results at (b) ?
Thanks to all of you guys and your responses.
I think I've found the answer. If you remove the line marked with (A) it works, if you leave it it doesn't. I'm pretty sure you could all figure out why that happens. Thanks again!
it's not neccessary to use callback, this should work as expected (haxe creates a local var in each loop):
var func = [];
for(i in 0...256)
func[i] = function() trace(i);
func[0]();
func[127]();
The one you show is the expected/desired behavior. To retain the value of "i" you must use "callback":
/* not pseudo code ;) */
var func = [];
for(i in 0...256)
func[i] = callback(function(v) trace(v), i);
func[0]();
func[127]();
func[256]();

PEG for Python style indentation

How would you write a Parsing Expression Grammar in any of the following Parser Generators (PEG.js, Citrus, Treetop) which can handle Python/Haskell/CoffeScript style indentation:
Examples of a not-yet-existing programming language:
square x =
x * x
cube x =
x * square x
fib n =
if n <= 1
0
else
fib(n - 2) + fib(n - 1) # some cheating allowed here with brackets
Update:
Don't try to write an interpreter for the examples above. I'm only interested in the indentation problem. Another example might be parsing the following:
foo
bar = 1
baz = 2
tap
zap = 3
# should yield (ruby style hashmap):
# {:foo => { :bar => 1, :baz => 2}, :tap => { :zap => 3 } }
Pure PEG cannot parse indentation.
But peg.js can.
I did a quick-and-dirty experiment (being inspired by Ira Baxter's comment about cheating) and wrote a simple tokenizer.
For a more complete solution (a complete parser) please see this question: Parse indentation level with PEG.js
/* Initializations */
{
function start(first, tail) {
var done = [first[1]];
for (var i = 0; i < tail.length; i++) {
done = done.concat(tail[i][1][0])
done.push(tail[i][1][1]);
}
return done;
}
var depths = [0];
function indent(s) {
var depth = s.length;
if (depth == depths[0]) return [];
if (depth > depths[0]) {
depths.unshift(depth);
return ["INDENT"];
}
var dents = [];
while (depth < depths[0]) {
depths.shift();
dents.push("DEDENT");
}
if (depth != depths[0]) dents.push("BADDENT");
return dents;
}
}
/* The real grammar */
start = first:line tail:(newline line)* newline? { return start(first, tail) }
line = depth:indent s:text { return [depth, s] }
indent = s:" "* { return indent(s) }
text = c:[^\n]* { return c.join("") }
newline = "\n" {}
depths is a stack of indentations. indent() gives back an array of indentation tokens and start() unwraps the array to make the parser behave somewhat like a stream.
peg.js produces for the text:
alpha
beta
gamma
delta
epsilon
zeta
eta
theta
iota
these results:
[
"alpha",
"INDENT",
"beta",
"gamma",
"INDENT",
"delta",
"DEDENT",
"DEDENT",
"epsilon",
"INDENT",
"zeta",
"DEDENT",
"BADDENT",
"eta",
"theta",
"INDENT",
"iota",
"DEDENT",
"",
""
]
This tokenizer even catches bad indents.
I think an indentation-sensitive language like that is context-sensitive. I believe PEG can only do context-free langauges.
Note that, while nalply's answer is certainly correct that PEG.js can do it via external state (ie the dreaded global variables), it can be a dangerous path to walk down (worse than the usual problems with global variables). Some rules can initially match (and then run their actions) but parent rules can fail thus causing the action run to be invalid. If external state is changed in such an action, you can end up with invalid state. This is super awful, and could lead to tremors, vomiting, and death. Some issues and solutions to this are in the comments here: https://github.com/dmajda/pegjs/issues/45
So what we are really doing here with indentation is creating something like a C-style blocks which often have their own lexical scope. If I were writing a compiler for a language like that I think I would try and have the lexer keep track of the indentation. Every time the indentation increases it could insert a '{' token. Likewise every time it decreases it could inset an '}' token. Then writing an expression grammar with explicit curly braces to represent lexical scope becomes more straight forward.
You can do this in Treetop by using semantic predicates. In this case you need a semantic predicate that detects closing a white-space indented block due to the occurrence of another line that has the same or lesser indentation. The predicate must count the indentation from the opening line, and return true (block closed) if the current line's indentation has finished at the same or shorter length. Because the closing condition is context-dependent, it must not be memoized.
Here's the example code I'm about to add to Treetop's documentation. Note that I've overridden Treetop's SyntaxNode inspect method to make it easier to visualise the result.
grammar IndentedBlocks
rule top
# Initialise the indent stack with a sentinel:
&{|s| #indents = [-1] }
nested_blocks
{
def inspect
nested_blocks.inspect
end
}
end
rule nested_blocks
(
# Do not try to extract this semantic predicate into a new rule.
# It will be memo-ized incorrectly because #indents.last will change.
!{|s|
# Peek at the following indentation:
save = index; i = _nt_indentation; index = save
# We're closing if the indentation is less or the same as our enclosing block's:
closing = i.text_value.length <= #indents.last
}
block
)*
{
def inspect
elements.map{|e| e.block.inspect}*"\n"
end
}
end
rule block
indented_line # The block's opening line
&{|s| # Push the indent level to the stack
level = s[0].indentation.text_value.length
#indents << level
true
}
nested_blocks # Parse any nested blocks
&{|s| # Pop the indent stack
# Note that under no circumstances should "nested_blocks" fail, or the stack will be mis-aligned
#indents.pop
true
}
{
def inspect
indented_line.inspect +
(nested_blocks.elements.size > 0 ? (
"\n{\n" +
nested_blocks.elements.map { |content|
content.block.inspect+"\n"
}*'' +
"}"
)
: "")
end
}
end
rule indented_line
indentation text:((!"\n" .)*) "\n"
{
def inspect
text.text_value
end
}
end
rule indentation
' '*
end
end
Here's a little test driver program so you can try it easily:
require 'polyglot'
require 'treetop'
require 'indented_blocks'
parser = IndentedBlocksParser.new
input = <<END
def foo
here is some indented text
here it's further indented
and here the same
but here it's further again
and some more like that
before going back to here
down again
back twice
and start from the beginning again
with only a small block this time
END
parse_tree = parser.parse input
p parse_tree
I know this is an old thread, but I just wanted to add some PEGjs code to the answers. This code will parse a piece of text and "nest" it into a sort of "AST-ish" structure. It only goes one deep and it looks ugly, furthermore it does not really use the return values to create the right structure but keeps an in-memory tree of your syntax and it will return that at the end. This might well become unwieldy and cause some performance issues, but at least it does what it's supposed to.
Note: Make sure you have tabs instead of spaces!
{
var indentStack = [],
rootScope = {
value: "PROGRAM",
values: [],
scopes: []
};
function addToRootScope(text) {
// Here we wiggle with the form and append the new
// scope to the rootScope.
if (!text) return;
if (indentStack.length === 0) {
rootScope.scopes.unshift({
text: text,
statements: []
});
}
else {
rootScope.scopes[0].statements.push(text);
}
}
}
/* Add some grammar */
start
= lines: (line EOL+)*
{
return rootScope;
}
line
= line: (samedent t:text { addToRootScope(t); }) &EOL
/ line: (indent t:text { addToRootScope(t); }) &EOL
/ line: (dedent t:text { addToRootScope(t); }) &EOL
/ line: [ \t]* &EOL
/ EOF
samedent
= i:[\t]* &{ return i.length === indentStack.length; }
{
console.log("s:", i.length, " level:", indentStack.length);
}
indent
= i:[\t]+ &{ return i.length > indentStack.length; }
{
indentStack.push("");
console.log("i:", i.length, " level:", indentStack.length);
}
dedent
= i:[\t]* &{ return i.length < indentStack.length; }
{
for (var j = 0; j < i.length + 1; j++) {
indentStack.pop();
}
console.log("d:", i.length + 1, " level:", indentStack.length);
}
text
= numbers: number+ { return numbers.join(""); }
/ txt: character+ { return txt.join(""); }
number
= $[0-9]
character
= $[ a-zA-Z->+]
__
= [ ]+
_
= [ ]*
EOF
= !.
EOL
= "\r\n"
/ "\n"
/ "\r"

Resources