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.
Related
Statically typed vs dynamically typed has been asked repeatedly on stackoverflow, for example here.
The consensus seems to be (quoting from the top answer of the above link):
A language is statically typed if the type of a variable is known at compile time.
And a dynamic language:
A language is dynamically typed if the type is associated with run-time values, and not named variables/fields/etc.
Perl seems to be statically typed by this (or other common definitions of static/dynamic typing). It has 3 types: scalar, array, hash (ignoring things like references for simplicity's sake). Types are declared along with variables:
my $x = 10; # declares a scalar variable named x
my #y = (1, 2, 3); # declares an array variable named y
my %z = (one => 1, two => 2); # declares a hash variable named z
The $, # and % above tell Perl which type you want; I'd count this as a form of explicit typing.
Once x has been declared as a scalar, as above, it's impossible to store a non-scalar value in x:
$x = #y; # x is now 3
Will convert y to a scalar (in Perl, array to scalar conversion result in the length of the array). I blame this on weak typing (Perl very liberally allows conversions between its 3 types), rather than dynamic typing.
Whereas in most statically typed languages, such an assignment would be an error, in Perl it is ok because of implicit conversions (similar to how bool x = 1; is fine in C/C++, but not in Java: both are statically typed, but Java is more strongly typed in this case). The only reason this conversion happened at all in Perl is because of the type of x, which again suggests Perl is statically typed.
Another argument people have against Perl being statically typed is that floats, ints, and strings are all stored in the same type of variable (scalars). But this really has nothing to do with static or dynamic typing. Within Perl's type system (which has only 3 types), there is no difference between floats, ints and strings. These all have type scalar. This is similar to saying C89 isn't statically typed because it used the int type to represent both ints and bools.
Obviously, this line of reasoning is ridiculous. Perl has very little in common with what most people think of as statically typed languages like C/C++, Java, OCaml, etc.
My question is, what's wrong with this line of reasoning?
I disagree on there being a consensus on the definitions you posted. But like your claim, that's opinion-based, and thus off-topic.
The posted definitions of "statically-typed language" and "dynamically-typed language" are useless. These are imaginary buckets into which very few languages fit.
According to the definition of statically-typed language you posted, Perl is a statically-typed language.
The type of $a is known to be a scalar at compile-time.
The type of #a is known to be an array at compile-time.
According to the definition of statically-typed language you posted, Perl isn't a statically-typed language.
$a could contain a signed integer (IV).
$a could contain a string (PV).
$a could contain a reference (RV) to an object of class Foo.
According to the definition of dynamically-typed language you posted, Perl is a dynamically-typed language.
$a could contain a signed integer (IV).
$a could contain a string (PV).
$a could contain a reference (RV) to an object of class Foo.
According to the definition of dynamically-typed language you posted, Perl isn't a dynamically-typed language.
The type of $a is known to be a scalar at compile-time.
The type of #a is known to be an array at compile-time.
Similarly, C++, C#, Java, BASIC and assembler languages are both/neither statically-typed and dynamically-typed. Even C doesn't fit the posted definition of statically-typed perfectly.
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.))
I am diving into Scala's string interpolation feature and I wonder if it is safe to use it. String interpolation allows us to evaluate expression like:
println(s"Hello World! ${for (i <- 1 to 100) println(s"other values $i")}")
My doubt is if we should evaluate expression in interpolated string. I see a lot of Scala code where other developers are using this feature like in example and don't know if this is correct and safe.
I would never use it and I would not want my colleagues to use it.
Two things are essentially off:
String interpolation is a nice feature because it makes concatenation of values easy to read... unless you stick an entire scala program in there :)
Not only there's a complex expression in there, but you're using a side-effect, so in the process of evaluating the interpolation 100 values will be printed. So you get
other values 1
other values 2
...
other values 100
Hello World! ()
Where the () is the return value of the for-comprehension, i.e. Unit.
I would save myself (and my colleagues) tremendous headaches and just do
println(s"Hello World!")
for (i <- 1 to 100) {
println(s"other values $i")
}
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.
I'm translating a script from Z shell to Fish, and I've got this one part I can't figure out how to translate:
for (( i=0; i < $COLUMNS; i++ )); do
printf $1
done
The only documentation for for loops I can find in Fish is for this kind. How would I do this in Fish?
It appears that the Fish shell does not have that kind of for loop, but instead requires you to take a different approach. (The philosophy is apparently to rely on as few syntactic structures and operators as possible, and do as much with commands as possible.)
Here's how I did it, although I assume there are better ways:
for CHAR in (seq $COLUMNS)
printf $argv[1]
end
This appears inside a function, hence the $argv[1].
I believe the answer from #iconoclast is the correct answer here.
I am here just to give an (not better) alternative.
a brief search in fish shell seems suggest it provides a while-loop in a form of :
while true
echo "Loop forever"
end
As in C/C++ 101, we learned that for loop can be (mostly) translated to a while loop by:
for (A; B; C) {
D;
}
translates to
A;
while (B) {
D;
C;
}
That's what you can consider if the condition and "incrementation" is not a straight-forward one.