One thing I love about Scala is that they give you multiple ways to write your statements, but this also raises some questions for me.
I have been fiddling around with a simple if statement, and discovered that it's behaviour is not as I would expect it to be. Have a look at the following code snippet:
var a = 0
var b = 0
if(false)
a += 1
b += 1
println(a) // 0
println(b) // 1
In this small example I would assume that both a and b will be zero at the end of the script, but this is not the case. It does work like I would expect when I add curly braces to the if statement.
It might be that I'm missing something here, but to me this seems like a rather confusing syntax. It could be easily overlooked when debugging someone else's code, so I am very curious about the reasons behind this syntax style.
Any opinions / explanations would be appreciated!
Why? It makes perfect sense. Scala is not like python with significant white space (actually your snippets look a lot like python ;)). If you want your if to govern multiple statements you need curly braces.
In languages that work like this, style guides often recommend always using a curly brace after an if to avoid the exact confusion you are taking about.
Personally, I have no problem with if statements followed by a single line and no curly brace.
The syntax for if is (simplified):
if (<bool expr>) <expr> [else <expr>]
Your
if(false)
a += 1
b += 1
is understood as
if (false) a += 1
b += 1
because a += 1 is an expression. Maybe it is clearer with curly braces
if (false) {
a += 1
}
b += 1
Note that block of code is an expression as well that evaluates to whatever last expression inside it evaluates to. So to have both expressions inside the if you need to put them in a block
if (false) {
a += 1
b += 1
}
There is of course no python-like block definition through indentation.
Related
The language guide says:
Swift doesn’t require you to write a semicolon (;) after each statement in your code, although you can do so if you wish. However, semicolons are required if you want to write multiple separate statements on a single line.
This implies that Swift uses newlines as statement terminators. Does every statement need to fit on a single line? Or is it possible to insert a newline within a single statement - and if so, what are the rules that determine whether or not a newline terminates a statement?
Swift can have newlines in statements. It is so common in complex commands like this:
var query = HouseholdInfoTable.table
.select(HouseholdInfoTable.uuid.distinct, HouseholdInfoTable.table[*])
.join(PersonInfoTable.table, on: PersonInfoTable.householdUuid == HouseholdInfoTable.uuid)
.filter(HouseholdInfoTable.houseNumber == houseNumber)
.order(HouseholdInfoTable.sortName)
But you can have simple statements broken up, like this:
let a = 1
+ 2
let b = 1 +
2
Generally you can split the line across operands or punctuation
You can do multiline comments with line feeds in them like this:
let bigComment = """
anythingYou want can go here
asdlkasdkljfad
askjf
"""
Swift's style guide has more in-depth information:
https://google.github.io/swift/#line-wrapping
Playgrounds are a good place to see what the compiler handles.
I'm looking to create a macro in P6 which converts its argument to a string.
Here's my macro:
macro tfilter($expr) {
quasi {
my $str = Q ({{{$expr}}});
filter-sub $str;
};
}
And here is how I call it:
my #some = tfilter(age < 50);
However, when I run the program, I obtain the error:
Unable to parse expression in quote words; couldn't find final '>'
How do I fix this?
Your use case, converting some code to a string via a macro, is very reasonable. There isn't an established API for this yet (even in my head), although I have come across and thought about the same use case. It would be nice in cases such as:
assert a ** 2 + b ** 2 == c ** 2;
This assert statement macro could evaluate its expression, and if it fails, it could print it out. Printing it out requires stringifying it. (In fact, in this case, having file-and-line information would be a nice touch also.)
(Edit: 007 is a language laboratory to flesh out macros in Perl 6.)
Right now in 007 if you stringify a Q object (an AST), you get a condensed object representation of the AST itself, not the code it represents:
$ bin/007 -e='say(~quasi { 2 + 2 })'
Q::Infix::Addition {
identifier: Q::Identifier "infix:+",
lhs: Q::Literal::Int 2,
rhs: Q::Literal::Int 2
}
This is potentially more meaningful and immediate than outputting source code. Consider also the fact that it's possible to build ASTs that were never source code in the first place. (And people are expected to do this. And to mix such "synthetic Qtrees" with natural ones from programs.)
So maybe what we're looking at is a property on Q nodes called .source or something. Then we'd be able to do this:
$ bin/007 -e='say((quasi { 2 + 2 }).source)'
2 + 2
(Note: doesn't work yet.)
It's an interesting question what .source ought to output for synthetic Qtrees. Should it throw an exception? Or just output <black box source>? Or do a best-effort attempt to turn itself into stringified source?
Coming back to your original code, this line fascinates me:
my $str = Q ({{{$expr}}});
It's actually a really cogent attempt to express what you want to do (turn an AST into its string representation). But I doubt it'll ever work as-is. In the end, it's still kind of based on a source-code-as-strings kind of thinking à la C. The fundamental issue with it is that the place where you put your {{{$expr}}} (inside of a string quote environment) is not a place where an expression AST is able to go. From an AST node type perspective, it doesn't typecheck because expressions are not a subtype of quote environments.
Hope that helps!
(PS: Taking a step back, I think you're doing yourself a disservice by making filter-sub accept a string argument. What will you do with the string inside of this function? Parse it for information? In that case you'd be better off analyzing the AST, not the string.)
(PPS: Moritz++ on #perl6 points out that there's an unrelated syntax error in age < 50 that needs to be addressed. Perl 6 is picky about things being defined before they are used; macros do not change this equation much. Therefore, the Perl 6 parser is going to assume that age is a function you haven't declared yet. Then it's going to consider the < an opening quote character. Eventually it'll be disappointed that there's no >. Again, macros don't rescue you from needing to declare your variables up-front. (Though see #159 for further discussion.))
This is my first day of studying Scala (using the "Beginning Scala" book). When I read the for loops in Scala, there are 2 examples:
val books = List("Beginning Scala", "Beginning Groovy", "Beginning Java", "Scala in easy steps", "Scala in 24 hours")
[1]
for (book<-books if book.contains("Scala")) println(book)
[2]
for { book <- books
bookVal = book.toUpperCase()
}
println(bookVal)
The thing that confused me is:
In [1] for uses parentheses "()" to wrap the loop control block while in [2] it uses curly braces "{}". I wonder if this is just different syntax but the same purpose or if they actually mean something different?
Thanks
Curly braces are usually used if you have multiline expression or expression which contains few other experession. If you're able (or want) to write in single line using semicolons you may use parentheses. Every for loop you can write with curly braces but using of parentheses is reduced.
If some other case curly braces allow you to use easier syntax to write partial function or pattern matching.
If you write in REPL following code:
for (
i <- List(1,2,3)
y = i * i
) yield y
it wouldn't compile e.g.
I don't know a really good name for what I'm talking about, but, most programming languages use a syntax for assignment statements something like this:
(variable) (assignment operator) (expression)
And some have some special assignment operators, such as var1 += var2 which is equivalent tovar1 = var1 + var2.
My question is basically, is there any language that would treat += like above, but also have an =+ operator so that var1 =+ var2 would be equivalent to var2 = var2 + var1?
Essentially, are there programming languages with "mirrorable" assignment operators, so that the variable on the right is what gets assignment a new variable (as opposed to the one on the left)?
Edit:
I suppose a much better example of what I'm referring to would be a language in which you can have both (variable) (assignment operator) (expression) and (expression) (assignment operator) (variable) as valid statements.
Authors of programming languages usually try to keep their language as simple as possible, without any unnecessary redundancy. So having any kind of two-side evaluation is redundant and unnecessary. It will only make the language specification 20 pages longer. I think there is no language with this feature.
By the way, your "grammar" (syntax rules) is not clear. What if someone writes
var x = 3, y = 2;
x = y;
By the way, Pascal has a "direction" of assignment. Actually, you can write your code as
var x = 3, y = 2;
x := y;
y =: x;
and write your own simple preprocessor for that, but again, I think it is just a complication of "clean" language.
What you propose is just a way to make code harder to read. There is no value in having a =+ operator if it's just synthatic sugar for writing your variables in a different order. But since you're into this weird stuff, you would surely love languages like Befunge and Piet, which, in a somewhat twisted way, do support that.
Some COBOL instructions are like this. E.g. ADD B TO A is the equivalent of "A += B" in other languages.
Is there any reason to use a scalar comma operator anywhere other than in a for loop?
Since the Perl scalar comma is a "port" of the C comma operator, these comments are probably apropos:
Once in a while, you find yourself in
a situation in which C expects a
single expression, but you have two
things you want to say. The most
common (and in fact the only common)
example is in a for loop, specifically
the first and third controlling
expressions. What if (for example) you
want to have a loop in which i counts
up from 0 to 10 at the same time that
j is counting down from 10 to 0?
So, your instinct that it's mainly useful in for loops is a good one, I think.
I occasionally use it in the conditional (sometimes erroneously called "the ternary") operator, if the code is easier to read than breaking it out into a real if/else:
my $blah = condition() ? do_this(), do_that() : do_the_other_thing();
It could also be used in some expression where the last result is important, such as in a grep expression, but in this case it's just the same as if a semicolon was used:
my #results = grep { setup(), condition() } #list;