In Scala, are semicolons necessary in some situations? - scala

I'm studying Scala and trying to use it in my recent projects. And problems come. Here's one of my problem about necessity of semicolons. This is my example:
var str = "123.4"
var d = str toDouble
if(d > 10)
println("Larger than 10")
These codes cannot be compiled. Because if(d > 10) println("Larger than 10") returns value and compiler thinks this value is a parameter of toDouble method. However, toDouble doesn't have a parameter. This causes error.
The easiest way to solve this is adding a semicolon at the end of line 2. Just like this:
var str = "123.4"
var d = str toDouble;
if(d > 10)
println("Larger than 10")
This confused me and I thought I don't need semicolons at all as I won't put two statements at same line. It makes me uncomfortable that some lines end with semicolon while the others don't. Also, does it makes sense?

Aggregating possible answers: To write same thing without syntax error you could use:
Semicolon
var d = str toDouble;
if (d > 10) println("Larger than 10")
Dot Syntax
var d = str.toDouble
if (d > 10) println("Larger than 10")
Parenthesis
var d = (str toDouble)
if (d > 10) println("Larger than 10")
Braces
var d = {str toDouble}
if (d > 10) println("Larger than 10")
Empty line separator
var d = str toDouble
if (d > 10) println("Larger than 10")
Choose the one which suits your style.
But in normal (non-DSL) code you will usually meet dotted version
A [most] usual use of semicolon is inside simple for expressions with several bindings.
for(i <- 1 to 4; j <- 1 until i) println(f"$j < $i")
Which by the way could be refactored to semicolonless version too:
for{i <- 1 to 4
j <- 1 until i} println(f"$j < $i")

Semicolons are sometimes required when using postfix operators. This is part of the reason why postfix operators are a language feature that you'll be warned about if you haven't explicitly enabled them. You could use the str.toDouble syntax instead.

As mentioned by Imm, postfix operators are an added feature. By importing scala.language.postfixOps you enable the compiler to acccept postfix syntax, hence this works
import scala.language.postfixOps
var str = "123.4"
var d = str toDouble
if(d > 10)
println("Larger than 10")

Yes, you need to put a semicolon sometimes, to make compiler understand that value next is not a parameter to the previous one. Like in your case:
var str = "123.4"
In code above, string ("123.4") does not takes any paramater so compiler automatically understands that it's end of line and any variable or function next to it is start of new line. But in case:
var d = str toDouble
As we can pass parameters to toDouble method, so compiler will understand that variable next to it is parameter for the same, to avoid these kind of situations we have to make put semicolon and make compiler understand about end of line.

Related

Julia: Macros, Expressions and Meta.parse

All these following lines of code are Julia expressions:
x = 10
1 + 1
println("hi")
if you want to pass an expression to a macro, it works like this. Macro foo just returns the given expression, which will be executed:
macro foo(ex)
return ex
end
#foo println("yes") # prints yes
x = #foo 1+1
println(x) # prints 2
If you want to convert a string into an expression, you can use Meta.parse():
string = "1+1"
expr = Meta.parse(string)
x = #foo expr
println(x) # prints 1 + 1
But, obviously, the macro treats expr as a symbol. What am i getting wrong here?
Thanks in advance!
Macro hygiene is important "macros must ensure that the variables they introduce in their returned expressions do not accidentally clash with existing variables in the surrounding code they expand into." There is a section in the docs. It is easiest just to show a simple case:
macro foo(x)
return :($x)
end
When you enter an ordinary expression in the REPL, it is evaluated immediately. To suppress that evaluation, surround the expression with :( ).
julia> 1 + 1
2
julia> :(1 + 1)
:(1 + 1)
# note this is the same result as you get using Meta.parse
julia> Meta.parse("1 + 1")
:(1 + 1)
So, Meta.parse will convert an appropriate string to an expression. And if you eval the result, the expression will be evaluated. Note that printing a simple expression removes the outer :( )
julia> expr = Meta.parse("1 + 1")
:(1 + 1)
julia> print(expr)
1 + 1
julia> result = eval(expr)
2
Usually, macros are used to manipulate things before the usual evaluation of expressions; they are syntax transformations, mostly. Macros are performed before other source code is compiled/evaluated/executed.
Rather than seeking a macro that evaluates a string as if it were typed directly into the REPL (without quotes), use this function instead.
evalstr(x::AbstractString) = eval(Meta.parse(x))
While I do not recommend this next macro, it is good to know the technique.
A macro named <name>_str is used like this <name>"<string contents>" :
julia> macro eval_str(x)
:(eval(Meta.parse($x)))
end
julia> eval"1 + 1"
2
(p.s. do not reuse Base function names as variable names, use str not string)
Please let me know if there is something I have not addressed.

One-liner for if then [duplicate]

This question already has answers here:
ternary operator in matlab
(12 answers)
Closed 8 years ago.
Is there a one-liner in MATLAB for this?
if a > b
foo = 'r';
else
foo = 'g';
end
There is no syntactic sugar for one-line if-statements in MatLab, but if your statement is really simple you could write it in one line.
I used to have one-line if-statements like that in my old project:
if (k < 1); k = 1; end;
In your case it'll look something like:
if a > b; foo = 'r'; else; foo = 'g'; end;
or, if you don't like semicolons
if a > b, foo = 'r'; else, foo = 'g'; end
Not as pretty as you may have expected, though.
Not as elegant as a C style ternary operator but you can take advantage of the fact that matlab will automatically cast logicals into doubles in this situation. So you can just multiply your desired result for true (r in this case) by your condition (a > b), and add that to the product of your desired result for false (i.e. g) with the not of your condition:
foo = (a > b)*c + (~(a > b))*d
so if we let c = 'r' and d = 'g' then all we need to do is cast foo back to a char at the end:
char(foo)
or
char((a > b)*'r' + ~(a > b)*'g')
Note that this will only work if c and d have the same dimensions (because of the +)...
Try to avoid using if statements in matlab, and just convert your logic to (vector) math:
foo = 1 + (a <= b)
Edit:
For the more general case, of assigning 'r' or 'g', you can use:
col = {'r', 'g'};
foo = col(1 + (a > b));
So for example with an isGreen boolean you could do:
foo = col(1 + isGreen);
This could also be a boolean returning function
foo = col(1 + isGreen(a))

Fortran command-line arguments

In g++ I was using getopt_long to handle command-line options. Does there
exist the same thing for Gfortran?
I want to be able to pass aguments to some Fortran unit tests.
Currently I have the following. As one can notice I am taking care
of getting the key and value myself. When using C++ getopt_long
was doing this for me.
i = 1
Do
Call Get_command_argument (i, arg)
If (Len_trim (arg) == 0) Exit
pos = Index (arg, "=")
!!$ Long option argument.
If (arg(1:2) == "--") Then
If (pos == 0) Then
c = arg
val = ""
Else
c = arg(:pos-1)
val = arg(pos+1:)
End If
!!$ Short option argument.
Elseif (arg(1:1) == "-") Then
c = arg
val = arg(pos+1:)
!!$ Non option argument.
Else
c = arg
val = arg
End If
!!$------------------------------------------------------------
Select Case (c)
Case ("-b","--brief")
arg_brief = .True.
Case ("-h","--help")
arg_help = .True.
Case ("-v","-V","--version")
arg_version = .True.
! Output model geographical definition
Case ("-cunit")
arg_cunit = val
Case default
arg_nonopt = Trim (Adjustl (arg))
Write (*,*) "Warning: Non option argument"
End Select
i = i + 1
End Do
!!$-------------------------------------------------------------
!!$ [TODO] Get numbers from arg_cunit
If (arg_cunit .contains. "-") Then
If (arg_cunit .contains. ",") Then
!!$ "-" and "," are present.
Else
!!$ "-" only are present.
End If
Else If (arg_cunit .contains. ",") Then
!!$ "," only are present
End If
Look at COMMAND_ARGUMENT_COUNT and GET_COMMAND_ARGUMENT. e.g., in the gfortran manual. They are standard Fortran intrinsics.
Of course you can use GET_COMMAND_ARGUMENT as you already do but that is the easy part. The hard part of the problem is to fill your variables with various numerical, logical and string values according to those argument strings. That is what the the following does:
One can use a namelist for easy argument parsing. Just add the begin and end markers. It is not too flexible, though, but very simple!
A (very!) short google search for getopt reveals a couple of Fortran ports of this library (or similar ones which include parsing):
http://fortranwiki.org/fortran/show/getopt_long_module
http://www.dominik-epple.de/getoptions/
http://lagrange.mechse.illinois.edu/partmc/partmc-2.4.0/doc/html/getopt_8_f90_source.html
and
http://libsufr.sourceforge.net/doxygen/getopt_8f90_source.html (thanks to AstroFloyd)

number_in_month exercise

I am fresh on SML and doing a homework by that. "Write a function number_in_month that takes a list of dates and a month (i.e., an int) and returns how many dates in the list are in the given month."
That's what I worked out and cannot see anything wrong with it. Please help.
`
fun number_in_month (dates: (int*int*int) list,month:int) =
if ((#2 (hd dates)) = month)
then val flag=1 flag+number_in_month(tl dates, month)
else number_in_month((tl dates),month)`
REPL tells that: replacing VAL with EQUALOP.
You can't bind variables "that way". A binding of a variable is a declaration and thus cannot be done where an expression is expected.
In this case you have to use a let-in-end expression
fun foo x =
let
val a = 42
in
a*x
end
Your problem is endless recursion. Compiler can't get out of it because independ of result if..then..else you're running your function again
Try this:
fun number_in_month (dates: (int*int*int) list,month:int) =
if null dates
then 0
else if ((#2 (hd dates)) = month)
then val flag=1 flag+number_in_month(tl dates, month)
else number_in_month((tl dates),month)
I tried to fix it by myself and that was my solution:
fun number_in_month (dias: (int*int*int) list,mes:int) =
if null dias
then 0
else if ((#2 (hd dias)) = mes)
then let val flag = 1 + number_in_month(tl dias, mes)
in flag
end
else number_in_month((tl dias),mes)
I hope you can also use it!
The error message from REPL is confusing, but Jesper is right that you should use let-in-end expression, if you need assignment statement in functions. That will surely get you that error resolved.

Why does Scala's semicolon inference fail here?

On compiling the following code with Scala 2.7.3,
package spoj
object Prime1 {
def main(args: Array[String]) {
def isPrime(n: Int) = (n != 1) && (2 to n/2 forall (n % _ != 0))
val read = new java.util.Scanner(System.in)
var nTests = read nextInt // [*]
while(nTests > 0) {
val (start, end) = (read nextInt, read nextInt)
start to end filter(isPrime(_)) foreach println
println
nTests -= 1
}
}
}
I get the following compile time error :
PRIME1.scala:8: error: illegal start of simple expression
while(nTests > 0) {
^
PRIME1.scala:14: error: block must end in result expression, not in definition
}
^
two errors found
When I add a semicolon at the end of the line commented as [*], the program compiles fine. Can anyone please explain why does Scala's semicolon inference fail to work on that particular line?
Is it because scala is assuming that you are using the syntax a foo b (equivalent to a.foo(b)) in your call to readInt. That is, it assumes that the while loop is the argument to readInt (recall that every expression has a type) and hence the last statement is a declaration:
var ntests = read nextInt x
wherex is your while block.
I must say that, as a point of preference, I've now returned to using the usual a.foo(b) syntax over a foo b unless specifically working with a DSL which was designed with that use in mind (like actors' a ! b). It makes things much clearer in general and you don't get bitten by weird stuff like this!
Additional comment to the answer by oxbow_lakes...
var ntests = read nextInt()
Should fix things for you as an alternative to the semicolon
To add a little more about the semicolon inference, Scala actually does this in two stages. First it infers a special token called nl by the language spec. The parser allows nl to be used as a statement separator, as well as semicolons. However, nl is also permitted in a few other places by the grammar. In particular, a single nl is allowed after infix operators when the first token on the next line can start an expression -- and while can start an expression, which is why it interprets it that way. Unfortunately, although while can start a expression, a while statement cannot be used in an infix expression, hence the error. Personally, it seems a rather quirky way for the parser to work, but there's quite plausibly a sane rationale behind it for all I know!
As yet another option to the others suggested, putting a blank newline between your [*] line and the while line will also fix the problem, because only a single nl is permitted after infix operators, so multiple nls forces a different interpretation by the parser.