implicit conversion not performed on overloaded operator+'s arguments? [duplicate] - c++11

I do not understand why initializer lists cannot be used on the RHS of an operator. Consider:
class foo { };
struct bar
{
template<typename... T>
bar(T const&...) { }
};
foo& operator<<(foo& f, bar const&) { return f; }
int main()
{
foo baz;
baz << {1, -2, "foo", 4, 5};
return 0;
}
The latest Clang (gcc as well) complains:
clang.cc:14:9: error: initializer list cannot be used on the right hand side of operator '<<'
baz << {1, -2, "foo", 4, 5};
^ ~~~~~~~~~~~~~~~~~~~~
^ ~~~~~~~~~~~~~~~
Why would the C++ standard forbid this? Or put differently, why does this fail as opposed to
baz << bar{1, -2, "foo", 4, 5};
?

Indeed the final version of C++11 does not enable the use of initializer lists on the right-hand side (or left-hand side, for that matter) of a binary operator.
Firstly, initializer-lists are not expressions as defined in §5 of the Standard. The arguments of functions, as well as of binary operators, generally have to be expressions, and the grammar for expressions defined in §5 does not include the syntax for brace-init-lists (i.e. pure initializer-lists; note that a typename followed by a brace-init-list, such as bar {2,5,"hello",7} is an expression, though).
In order to be able to use pure initializer-lists conveniently, the standard defines various exceptions, which are summarized in the following (non-normative) note:
§8.5.4/1
[...] Note: List-initialization can be used
— as the initializer in a variable definition (8.5)
— as the initializer in a new expression (5.3.4)
— in a return statement (6.6.3)
— as a function argument (5.2.2)
— as a subscript (5.2.1)
— as an argument to a constructor invocation (8.5, 5.2.3)
— as an initializer for a non-static data member (9.2)
— in a mem-initializer (12.6.2)
— on the right-hand side of an assignment (5.17)
[...]
The fourth item above explicitly allows pure initializer-lists as function arguments (which is why operator<<(baz, {1, -2, "foo", 4, 5}); works), the fifth one allows it in subscript expressions (i.e. as argument of operator[], e.g. mymap[{2,5,"hello"}] is legal), and the last item allows them on the right-hand side of assignments (but not general binary operators).
There is no such exception for binary operators like +, * or <<, hence you can't put a pure initializer list (i.e. one that is not preceded with a typename) on either side of them.
As to the reasons for this, a draft/discussion paper N2215 by Stroustrup and Dos Reis from 2007 provides a lot of insight into many of the issues with initializer-lists in various contexts. Specifically, there is a section on binary operators (section 6.2):
Consider more general uses of initializer lists. For example:
v = v+{3,4};
v = {6,7}+v;
When we consider operators as syntactic sugar for functions, we naturally consider the above equivalent to
v = operator+(v,{3,4});
v = operator+({6,7},v);
It is therefore natural to extend the use of initializer lists to expressions. There are many uses where initializer lists combined with operators is a “natural” notation.
However, it is not trivial to write a LR(1) grammar that allows arbitrary use of initializer lists. A block also starts with a { so allowing an initializer list as the first (leftmost) entity of an expression would lead to chaos in the grammar.
It is trivial to allow initializer lists as the right-hand operand of binary operators, in
subscripts, and similar isolated parts of the grammar. The real problem is to allow ;a={1,2}+b; as an assignment-statement without also allowing ;{1,2}+b;. We suspect that allowing initializer lists as right-hand, but nor [sic] as left-hand arguments to most operators is too much of a kludge, [...]
In other words, initializer-lists are not enabled on the right-hand side because they are not enabled on the left-hand side, and they are not enabled on the left-hand side because that would have posed too big a challenge for parsers.
I wonder if the problem could have been simplified by picking a different symbol instead of curly braces for the initializer-list syntax.

Related

How does nested list-initialization forward its arguments?

In the initialization of a vector of pairs
std::vector<std::pair<int, std::string>> foo{{1.0, "one"}, {2.0, "two"}};
how am I supposed to interpret the construction of foo? As I understand it,
The constructor is called with braced initialization syntax so the overload vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() ); is strongly preferred and selected
The template parameter of std::initializer_list<T> is deduced to std::pair<int, std::string>
Each element of foo is a std::pair. However, std::pair has no overload accepting std::initializer_list.
I am not so sure about step 3. I know the inner braces can't be interpreted as std::initializer_list since they are heterogenous. What mechanism in the standard is actually constructing each element of foo? I suspect the answer has something to do with forwarding the arguments in the inner braces to the overload template< class U1, class U2 pair( U1&& x, U2&& y ); but I don't know what this is called.
EDIT:
I figure a simpler way to ask the same question would be: When one does
std::map<int, std::string> m = { // nested list-initialization
{1, "a"},
{2, {'a', 'b', 'c'} },
{3, s1}
as shown in the cppreference example, where in the standard does it say that {1, "a"}, {2, {'a', 'b', 'c'} }, and {3, s1} each get forwarded to the constructor for std::pair<int, std::string>?
Usually, expressions are analyzed inside-out: The inner expressions have types and these types then decide which meaning the outer operators have and which functions are to be called.
But initializer lists are not expressions, and have no type. Therefore, inside-out does not work. Special overload resolution rules are needed to account for initializer lists.
The first rule is: If there are constructors with a single parameter that is some initializer_list<T>, then in a first round of overload resolution only such constructors are considered (over.match.list).
The second rule is: For each initializer_list<T> candidate (there could be more than one of them per class, with different T each), it is checked that each initializer can be converted to T, and only those candidates remain where this works out (over.ics.list).
This second rule is basically, where the initializer-lists-have-no-type hurdle is taken and inside-out analysis is resumed.
Once overload resolution has decided that a particular initializer_list<T> constructor should be used, copy-initialization is used to initialize the elements of type T of the initializer list.
You are confusing two different concepts:
1) initializer lists
initializer_list<T>: that is mainly used for initialization of collections. In this case, all of the members should be of the same type. (not applicable for std::pair)
Example:
std::vector<int> vec {1, 2, 3, 4, 5};
2) Uniform initialization
Uniform initialization: in which the braces are used to construct and initialize some objects like structs, classes (with an appropriate constructor) and basic types (int, char, etc.).
Example:
struct X { int x; std::string s;};
X x{1, "Hi"}; // Not an initializer_list here.
Having mentioned that, for initialization of a std::pair with a brace initializer, you will need a constructor that takes two elements, i.e. the first and the second elements, not a std::initializer_list<T>. For example on my machine with VS2015 installed, this constructor looks like this:
template<class _Other1,
class _Other2,
class = enable_if_t<is_constructible<_Ty1, _Other1>::value
&& is_constructible<_Ty2, _Other2>::value>,
enable_if_t<is_convertible<_Other1, _Ty1>::value
&& is_convertible<_Other2, _Ty2>::value, int> = 0>
constexpr pair(_Other1&& _Val1, _Other2&& _Val2) // -----> Here the constructor takes 2 input params
_NOEXCEPT_OP((is_nothrow_constructible<_Ty1, _Other1>::value
&& is_nothrow_constructible<_Ty2, _Other2>::value))
: first(_STD forward<_Other1>(_Val1)), // ----> initialize the first
second(_STD forward<_Other2>(_Val2)) // ----> initialize the second
{ // construct from moved values
}

C++11 why the type of 'decltype(x)' and 'decltype((x))' are different?

I found they're different, and the language standard says what kind of type each statement should retrieve(difference between variable and expression). But I really wish to know why these 2 kinds of types should be different?
#include<stdio.h>
int x=0;
decltype((x)) y=x;
int main()
{
y=2;
printf("%d,",x);
decltype((1+2))&z=x;//OK (1+2) is an express, but why decltype should differ?
z=3;
printf("%d\n",x);
return 0;
}
The running result is '2,3'
So why decltype((int)) is int& by design, what's the consideration of C++ language design here? Any syntax consistency that requires such a design? (I don't wish to get "This is by design")
Thanks for your explanations.
If you read e.g. this decltype reference you will see
2) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, ...
3) If the argument is any other expression...
...
b) if the value category of expression is lvalue, then decltype yields T&;
[Emphasis mine]
And then a little further down the note
Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype(x) and decltype((x)) are often different types.
Because you use a parenthesized expression it is treated as an lvalue, meaning that 3.b above is active and decltype((x)) gives you int& if x is int.
It should be noted that while the reference isn't authoritative it is derived from the specification and generally reliable and correct.
From the C++11 specification ISO/IEC 14882:2011, section 7.1.6.2 [dcl.type.simple], sub-section 4:
The type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
— otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e
And with an example:
struct A { double x; };
const A* a = new A();
...
decltype((a->x)) x4 = x3; // type is const double&
Basically exactly what the previously linked reference said.
With your example, e in the specification is (x) (since you have declspec((x))). Now the first case doesn't fit because (x) is not an unparenthesized expression. The second case doesn't fit because (x) isn't an xvalue. The third case matches though, (x) is an lvalue of type int, leading decltype((x)) to be int&.
So the answer to your query is simply: Because the specification says so.
Well, The answer I see here is that "the specification says so". I looked into stroustrup's original drafts of decltype and this is what it says.
if expr in decltype(expr) is a variable or formal parameter the
programmer can trace down the variable’s or parameter’s declaration,
and the result of decltype is exactly the declared type. If expr is a
function invocation, the programmer can perform manual overload
resolution; the result of the decltype is the return type in the
prototype of the best matching function. The prototypes of the
built-in operators are defined by the standard, and if some are
missing, the rule that an lvalue has a reference type applies.
Look at the last statement here, I think that explains. Since parenthesis are built-in operators to indicate and expression.

Clang Comparison Bug with negative values in strongly typed enum?

I recently dealt with code using a strongly typed enum that contained negative values.
When comparing the values of the enum, I got weird results when compiling the code with Clang (3.3) while Gcc works just fine.
Here is a small example with an assert that fails.
enum class T: int { A = -1, B = 1 };
int main() {
T a = T::A, b = T::B;
assert(a < b);
}
Is this an actual bug? Or does clang behave correctly and gcc just offers some kind of legacy support?
It should be more intuitive that the following is well-formed:
T a = T::A;
assert(a == T::A);
But the equality operators (==, !=) have the same restrictions as the relational operators (<, <=, ..) [expr.eq]/1:
The == (equal to) and the != (not equal to) operators have the same semantic restrictions, conversions, and result type as the relational operators except for their lower precedence and truth-value result.
So if equality between values of a scoped enumeration type is well-defined, so should < be.
[expr.rel]/1
The operands shall have arithmetic, enumeration, or pointer type, or type std::nullptr_t.
Of course, the usual arithmetic conversions are performed on operands of arithmetic or enumeration type [expr.rel]/2, where the conversion is the identity conversion for scoped enumerations (no integral promotion, see [expr]/10 first bullet). However, [expr.rel]/5 explicitly states:
If both operands (after conversions) are of arithmetic or enumeration type, each of the operators shall yield
true if the specified relationship is true and false if it is false.
(emphasis mine)
Therefore, T::A < T::B should be well-formed and yield true.
As I already wrote in a comment, the assertion doesn't fail on clang++3.4 trunk 193040. I therefore assume it's a bug that has been fixed, even though I couldn't find a corresponding bug report.

List of Scala's "magic" functions

Where can I find a list of Scala's "magic" functions, such as apply, unapply, update, +=, etc.?
By magic-functions I mean functions which are used by some syntactic sugar of the compiler, for example
o.update(x,y) <=> o(x) = y
I googled for some combination of scala magic and synonyms of functions, but I didn't find anything.
I'm not interested with the usage of magic functions in the standard library, but in which magic functions exists.
As far as I know:
Getters/setters related:
apply
update
identifier_=
Pattern matching:
unapply
unapplySeq
For-comprehensions:
map
flatMap
filter
withFilter
foreach
Prefixed operators:
unary_+
unary_-
unary_!
unary_~
Beyond that, any implicit from A to B. Scala will also convert A <op>= B into A = A <op> B, if the former operator isn't defined, "op" is not alphanumeric, and <op>= isn't !=, ==, <= or >=.
And I don't believe there's any single place where all of Scala's syntactic sugars are listed.
In addition to update and apply, there are also a number of unary operators which (I believe) qualify as magical:
unary_+
unary_-
unary_!
unary_~
Add to that the regular infix/suffix operators (which can be almost anything) and you've got yourself the complete package.
You really should take a look at the Scala Language Specification. It is the only authoritative source on this stuff. It's not that hard to read (as long as you're comfortable with context-free grammars), and very easily searchable. The only thing it doesn't specify well is the XML support.
Sorry if it's not exactly answering your question, but my favorite WTF moment so far is # as assignment operator inside pattern match. Thanks to soft copy of "Programming in Scala" I found out what it was pretty quickly.
Using # we can bind any part of a pattern to a variable, and if the pattern match succeeds, the variable will capture the value of the sub-pattern. Here's the example from Programming in Scala (Section 15.2 - Variable Binding):
expr match {
case UnOp("abs", e # UnOp("abs", _)) => e
case _ =>
}
If the entire pattern match succeeds,
then the portion that matched the
UnOp("abs", _) part is made available
as variable e.
And here's what Programming Scala says about it.
That link no longer works. Here is one that does.
I'll also add _* for pattern matching on an arbitrary number of parameters like
case x: A(_*)
And operator associativity rule, from Odersky-Spoon-Venners book:
The associativity of an operator in Scala is determined by its last
character. As mentioned on <...>, any method that ends
in a ‘:’ character is invoked on its right operand, passing in the
left operand. Methods that end in any other character are the other
way around. They are invoked on their left operand, passing in the
right operand. So a * b yields a.*(b), but a ::: b yields b.:::(a).
Maybe we should also mention syntactic desugaring of for expressions which can be found here
And (of course!), alternative syntax for pairs
a -> b //converted to (a, b), where a and b are instances
(as correctly pointed out, this one is just an implicit conversion done through a library, so it's probably not eligible, but I find it's a common puzzler for newcomers)
I'd like to add that there is also a "magic" trait - scala.Dynamic:
A marker trait that enables dynamic invocations. Instances x of this trait allow method invocations x.meth(args) for arbitrary method names meth and argument lists args as well as field accesses x.field for arbitrary field names field.
If a call is not natively supported by x (i.e. if type checking fails), it is rewritten according to the following rules:
foo.method("blah") ~~> foo.applyDynamic("method")("blah")
foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
foo.field ~~> foo.selectDynamic("field")
foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
foo.arr(10) ~~> foo.applyDynamic("arr")(10)
As of Scala 2.10, defining direct or indirect subclasses of this trait is only possible if the language feature dynamics is enabled.
So you can do stuff like
import scala.language.dynamics
object Dyn extends Dynamic {
def applyDynamic(name: String)(a1: Int, a2: String) {
println("Invoked " + name + " on (" + a1 + "," + a2 + ")");
}
}
Dyn.foo(3, "x");
Dyn.bar(3, "y");
They are defined in the Scala Language Specification.
As far as I know, there are just three "magic" functions as you mentioned.
Scalas Getter and Setter may also relate to your "magic":
scala> class Magic {
| private var x :Int = _
| override def toString = "Magic(%d)".format(x)
| def member = x
| def member_=(m :Int){ x = m }
| }
defined class Magic
scala> val m = new Magic
m: Magic = Magic(0)
scala> m.member
res14: Int = 0
scala> m.member = 100
scala> m
res15: Magic = Magic(100)
scala> m.member += 99
scala> m
res17: Magic = Magic(199)

What are the precise rules for when you can omit parenthesis, dots, braces, = (functions), etc.?

What are the precise rules for when you can omit (omit) parentheses, dots, braces, = (functions), etc.?
For example,
(service.findAllPresentations.get.first.votes.size) must be equalTo(2).
service is my object
def findAllPresentations: Option[List[Presentation]]
votes returns List[Vote]
must and be are both functions of specs
Why can't I go:
(service findAllPresentations get first votes size) must be equalTo(2)
?
The compiler error is:
"RestServicesSpecTest.this.service.findAllPresentations
of type
Option[List[com.sharca.Presentation]]
does not take parameters"
Why does it think I'm trying to pass in a parameter? Why must I use dots for every method call?
Why must (service.findAllPresentations get first votes size) be equalTo(2) result in:
"not found: value first"
Yet, the "must be equalTo 2" of
(service.findAllPresentations.get.first.votes.size) must be equalTo 2, that is, method chaining works fine? - object chain chain chain param.
I've looked through the Scala book and website and can't really find a comprehensive explanation.
Is it in fact, as Rob H explains in Stack Overflow question Which characters can I omit in Scala?, that the only valid use-case for omitting the '.' is for "operand operator operand" style operations, and not for method chaining?
You seem to have stumbled upon the answer. Anyway, I'll try to make it clear.
You can omit dot when using the prefix, infix and postfix notations -- the so called operator notation. While using the operator notation, and only then, you can omit the parenthesis if there is less than two parameters passed to the method.
Now, the operator notation is a notation for method-call, which means it can't be used in the absence of the object which is being called.
I'll briefly detail the notations.
Prefix:
Only ~, !, + and - can be used in prefix notation. This is the notation you are using when you write !flag or val liability = -debt.
Infix:
That's the notation where the method appears between an object and it's parameters. The arithmetic operators all fit here.
Postfix (also suffix):
That notation is used when the method follows an object and receives no parameters. For example, you can write list tail, and that's postfix notation.
You can chain infix notation calls without problem, as long as no method is curried. For example, I like to use the following style:
(list
filter (...)
map (...)
mkString ", "
)
That's the same thing as:
list filter (...) map (...) mkString ", "
Now, why am I using parenthesis here, if filter and map take a single parameter? It's because I'm passing anonymous functions to them. I can't mix anonymous functions definitions with infix style because I need a boundary for the end of my anonymous function. Also, the parameter definition of the anonymous function might be interpreted as the last parameter to the infix method.
You can use infix with multiple parameters:
string substring (start, end) map (_ toInt) mkString ("<", ", ", ">")
Curried functions are hard to use with infix notation. The folding functions are a clear example of that:
(0 /: list) ((cnt, string) => cnt + string.size)
(list foldLeft 0) ((cnt, string) => cnt + string.size)
You need to use parenthesis outside the infix call. I'm not sure the exact rules at play here.
Now, let's talk about postfix. Postfix can be hard to use, because it can never be used anywhere except the end of an expression. For example, you can't do the following:
list tail map (...)
Because tail does not appear at the end of the expression. You can't do this either:
list tail length
You could use infix notation by using parenthesis to mark end of expressions:
(list tail) map (...)
(list tail) length
Note that postfix notation is discouraged because it may be unsafe.
I hope this has cleared all the doubts. If not, just drop a comment and I'll see what I can do to improve it.
Class definitions:
val or var can be omitted from class parameters which will make the parameter private.
Adding var or val will cause it to be public (that is, method accessors and mutators are generated).
{} can be omitted if the class has no body, that is,
class EmptyClass
Class instantiation:
Generic parameters can be omitted if they can be inferred by the compiler. However note, if your types don't match, then the type parameter is always infered so that it matches. So without specifying the type, you may not get what you expect - that is, given
class D[T](val x:T, val y:T);
This will give you a type error (Int found, expected String)
var zz = new D[String]("Hi1", 1) // type error
Whereas this works fine:
var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}
Because the type parameter, T, is inferred as the least common supertype of the two - Any.
Function definitions:
= can be dropped if the function returns Unit (nothing).
{} for the function body can be dropped if the function is a single statement, but only if the statement returns a value (you need the = sign), that is,
def returnAString = "Hi!"
but this doesn't work:
def returnAString "Hi!" // Compile error - '=' expected but string literal found."
The return type of the function can be omitted if it can be inferred (a recursive method must have its return type specified).
() can be dropped if the function doesn't take any arguments, that is,
def endOfString {
return "myDog".substring(2,1)
}
which by convention is reserved for methods which have no side effects - more on that later.
() isn't actually dropped per se when defining a pass by name paramenter, but it is actually a quite semantically different notation, that is,
def myOp(passByNameString: => String)
Says myOp takes a pass-by-name parameter, which results in a String (that is, it can be a code block which returns a string) as opposed to function parameters,
def myOp(functionParam: () => String)
which says myOp takes a function which has zero parameters and returns a String.
(Mind you, pass-by-name parameters get compiled into functions; it just makes the syntax nicer.)
() can be dropped in the function parameter definition if the function only takes one argument, for example:
def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }
But if it takes more than one argument, you must include the ():
def myOp2(passByNameString:(Int, String) => String) { .. }
Statements:
. can be dropped to use operator notation, which can only be used for infix operators (operators of methods that take arguments). See Daniel's answer for more information.
. can also be dropped for postfix functions
list tail
() can be dropped for postfix operators
list.tail
() cannot be used with methods defined as:
def aMethod = "hi!" // Missing () on method definition
aMethod // Works
aMethod() // Compile error when calling method
Because this notation is reserved by convention for methods that have no side effects, like List#tail (that is, the invocation of a function with no side effects means that the function has no observable effect, except for its return value).
() can be dropped for operator notation when passing in a single argument
() may be required to use postfix operators which aren't at the end of a statement
() may be required to designate nested statements, ends of anonymous functions or for operators which take more than one parameter
When calling a function which takes a function, you cannot omit the () from the inner function definition, for example:
def myOp3(paramFunc0:() => String) {
println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work
When calling a function that takes a by-name parameter, you cannot specify the argument as a parameter-less anonymous function. For example, given:
def myOp2(passByNameString:Int => String) {
println(passByNameString)
}
You must call it as:
myOp("myop3")
or
myOp({
val source = sourceProvider.source
val p = myObject.findNameFromSource(source)
p
})
but not:
myOp(() => "myop3") // Doesn't work
IMO, overuse of dropping return types can be harmful for code to be re-used. Just look at specification for a good example of reduced readability due to lack of explicit information in the code. The number of levels of indirection to actually figure out what the type of a variable is can be nuts. Hopefully better tools can avert this problem and keep our code concise.
(OK, in the quest to compile a more complete, concise answer (if I've missed anything, or gotten something wrong/inaccurate please comment), I have added to the beginning of the answer. Please note this isn't a language specification, so I'm not trying to make it exactly academically correct - just more like a reference card.)
A collection of quotes giving insight into the various conditions...
Personally, I thought there'd be more in the specification. I'm sure there must be, I'm just not searching for the right words...
There are a couple of sources however, and I've collected them together, but nothing really complete / comprehensive / understandable / that explains the above problems to me...:
"If a method body has more than one
expression, you must surround it with
curly braces {…}. You can omit the
braces if the method body has just one
expression."
From chapter 2, "Type Less, Do More", of Programming Scala:
"The body of the upper method comes
after the equals sign ‘=’. Why an
equals sign? Why not just curly braces
{…}, like in Java? Because semicolons,
function return types, method
arguments lists, and even the curly
braces are sometimes omitted, using an
equals sign prevents several possible
parsing ambiguities. Using an equals
sign also reminds us that even
functions are values in Scala, which
is consistent with Scala’s support of
functional programming, described in
more detail in Chapter 8, Functional
Programming in Scala."
From chapter 1, "Zero to Sixty: Introducing Scala", of Programming Scala:
"A function with no parameters can be
declared without parentheses, in which
case it must be called with no
parentheses. This provides support for
the Uniform Access Principle, such
that the caller does not know if the
symbol is a variable or a function
with no parameters.
The function body is preceded by "="
if it returns a value (i.e. the return
type is something other than Unit),
but the return type and the "=" can be
omitted when the type is Unit (i.e. it
looks like a procedure as opposed to a
function).
Braces around the body are not
required (if the body is a single
expression); more precisely, the body
of a function is just an expression,
and any expression with multiple parts
must be enclosed in braces (an
expression with one part may
optionally be enclosed in braces)."
"Functions with zero or one argument
can be called without the dot and
parentheses. But any expression can
have parentheses around it, so you can
omit the dot and still use
parentheses.
And since you can use braces anywhere
you can use parentheses, you can omit
the dot and put in braces, which can
contain multiple statements.
Functions with no arguments can be
called without the parentheses. For
example, the length() function on
String can be invoked as "abc".length
rather than "abc".length(). If the
function is a Scala function defined
without parentheses, then the function
must be called without parentheses.
By convention, functions with no
arguments that have side effects, such
as println, are called with
parentheses; those without side
effects are called without
parentheses."
From blog post Scala Syntax Primer:
"A procedure definition is a function
definition where the result type and
the equals sign are omitted; its
defining expression must be a block.
E.g., def f (ps) {stats} is
equivalent to def f (ps): Unit =
{stats}.
Example 4.6.3 Here is a declaration
and a de?nition of a procedure named
write:
trait Writer {
def write(str: String)
}
object Terminal extends Writer {
def write(str: String) { System.out.println(str) }
}
The code above is implicitly completed
to the following code:
trait Writer {
def write(str: String): Unit
}
object Terminal extends Writer {
def write(str: String): Unit = { System.out.println(str) }
}"
From the language specification:
"With methods which only take a single
parameter, Scala allows the developer
to replace the . with a space and omit
the parentheses, enabling the operator
syntax shown in our insertion operator
example. This syntax is used in other
places in the Scala API, such as
constructing Range instances:
val firstTen:Range = 0 to 9
Here again, to(Int) is a vanilla
method declared inside a class
(there’s actually some more implicit
type conversions here, but you get the
drift)."
From Scala for Java Refugees Part 6: Getting Over Java:
"Now, when you try "m 0", Scala
discards it being a unary operator, on
the grounds of not being a valid one
(~, !, - and +). It finds that "m" is
a valid object -- it is a function,
not a method, and all functions are
objects.
As "0" is not a valid Scala
identifier, it cannot be neither an
infix nor a postfix operator.
Therefore, Scala complains that it
expected ";" -- which would separate
two (almost) valid expressions: "m"
and "0". If you inserted it, then it
would complain that m requires either
an argument, or, failing that, a "_"
to turn it into a partially applied
function."
"I believe the operator syntax style
works only when you've got an explicit
object on the left-hand side. The
syntax is intended to let you express
"operand operator operand" style
operations in a natural way."
Which characters can I omit in Scala?
But what also confuses me is this quote:
"There needs to be an object to
receive a method call. For instance,
you cannot do “println “Hello World!”"
as the println needs an object
recipient. You can do “Console
println “Hello World!”" which
satisfies the need."
Because as far as I can see, there is an object to receive the call...
I find it easier to follow this rule of thumb: in expressions spaces alternate between methods and parameters. In your example, (service.findAllPresentations.get.first.votes.size) must be equalTo(2) parses as (service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2)). Note that the parentheses around the 2 have a higher associativity than the spaces. Dots also have higher associativity, so (service.findAllPresentations.get.first.votes.size) must be.equalTo(2)would parse as (service.findAllPresentations.get.first.votes.size).must(be.equalTo(2)).
service findAllPresentations get first votes size must be equalTo 2 parses as service.findAllPresentations(get).first(votes).size(must).be(equalTo).2.
Actually, on second reading, maybe this is the key:
With methods which only take a single
parameter, Scala allows the developer
to replace the . with a space and omit
the parentheses
As mentioned on the blog post: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 .
So perhaps this is actually a very strict "syntax sugar" which only works where you are effectively calling a method, on an object, which takes one parameter. e.g.
1 + 2
1.+(2)
And nothing else.
This would explain my examples in the question.
But as I said, if someone could point out to be exactly where in the language spec this is specified, would be great appreciated.
Ok, some nice fellow (paulp_ from #scala) has pointed out where in the language spec this information is:
6.12.3:
Precedence and associativity of
operators determine the grouping of
parts of an expression as follows.
If there are several infix operations in an expression, then
operators with higher precedence bind
more closely than operators with lower
precedence.
If there are consecutive infix operations e0 op1 e1 op2 . . .opn en
with operators op1, . . . , opn of the
same precedence, then all these
operators must have the same
associativity. If all operators are
left-associative, the sequence is
interpreted as (. . . (e0 op1 e1) op2
. . .) opn en. Otherwise, if all
operators are rightassociative, the
sequence is interpreted as e0 op1 (e1
op2 (. . .opn en) . . .).
Postfix operators always have lower precedence than infix operators. E.g.
e1 op1 e2 op2 is always equivalent to
(e1 op1 e2) op2.
The right-hand operand of a
left-associative operator may consist
of several arguments enclosed in
parentheses, e.g. e op (e1, . . .
,en). This expression is then
interpreted as e.op(e1, . . . ,en).
A left-associative binary operation e1
op e2 is interpreted as e1.op(e2). If
op is rightassociative, the same
operation is interpreted as { val
x=e1; e2.op(x ) }, where x is a fresh
name.
Hmm - to me it doesn't mesh with what I'm seeing or I just don't understand it ;)
There aren't any. You will likely receive advice around whether or not the function has side-effects. This is bogus. The correction is to not use side-effects to the reasonable extent permitted by Scala. To the extent that it cannot, then all bets are off. All bets. Using parentheses is an element of the set "all" and is superfluous. It does not provide any value once all bets are off.
This advice is essentially an attempt at an effect system that fails (not to be confused with: is less useful than other effect systems).
Try not to side-effect. After that, accept that all bets are off. Hiding behind a de facto syntactic notation for an effect system can and does, only cause harm.

Resources