Beginner Scala question, but I couldn't find the answer on here.
Similar to overloading in C++, I would expect the compiler can tell the difference between a method called - which takes one parameter (with the same type as the class) and the unary version of - which takes no parameters, so why is unary_ needed?
The unary_ prefix for unary prefix operators is a bit misleading: it's more about the prefix part than the unary part. You need some way to distinguish
!foo // unary prefix !
from
foo! // unary postfix !
Remember: Scala doesn't actually have operators. There are two ways to call a method, either with a . or with whitespace:
foo.bar(1, "two")
foo bar(1, "two")
And when you have a single argument, you can leave off the parentheses:
foo plus(1)
foo plus 1
Lastly, (almost) any character is legal in an identifier:
foo plus 1
foo + 1
Now it looks like Scala has a binary infix + operator, but it actually doesn't. It's just a normal method called with normal method calling syntax.
What I said above isn't fully true, however. If Scala didn't have support for operators and it all was just normal method calling, then
2 + 3 * 4
would evaluate to 20 (like it does in Smalltalk, Self and Newspeak for example) instead of 14. So, there is a little bit of support for operators in Scala (two little bits, actually). When a method is called with whitespace (so-called "operator syntax") instead of the ., and that method starts with an operator character, then Scala will respect operator precedence.
And the other little bit of operator support is that there are some operators that you would like to have, but that cannot be easily expressed as a method call. It works fine for binary infix operators and unary postfix operators:
foo op bar // same as:
foo.op(bar)
foo op // same as:
foo.op
But not for prefix or "around-fix" operators:
!foo
foo(bar)
So, there are a couple of special syntactic sugar translation rules:
!foo
foo.unary_!
// same for +, - and ~
foo(bar)
foo.apply(bar)
foo(bar) = 1
foo.update(bar, 1)
foo += 1
foo.+=(1) // but if this doesn't compile, then the compiler will also try
foo = foo.+(1)
And the reason why there needs to be an underscore between the alphanumeric and the "operator" part in a method name is because you wouldn't know whether
foo!
means
foo.!
or
this.foo!
Thus, foo! as a method name is illegal, it needs to be called foo_!.
Because in scala it is totally fine to create a method named -, that takes no arguments. How would you distinguish between a normal and a unary method? For example ! has a totally different meaning as unary, than as post fix operator.
Related
The Q Tips book (Nick Psaris) shows the
following function (Chapter 10):
q)merge:`time xdesc upsert
As it is stated, it corresponds to function composition. I see the pattern: the
expression supplies a function that takes both arguments for upsert and then
uses its result to feed time xdesc. However the syntax feels weird, since
I would expect upsert to be the second argument of the xdesc invocation.
Aiming at simplifying the expression, I could see that the very same scenario
applies here:
q)f:1+*
q)f[2;3]
7
If we show its result, we can clearly see that f behaves as expected:
q)f
+[1]*
However, If we slightly modify the function, the meaning of the expression is
completely different:
q)g:+[1;]*
q)g[2;3]
'rank
[0] g[2;3]
^
In fact, +[1;] is passed as first argument to the * operator instead,
leading us to a rank error:
q)g
*[+[1;]]
I could also notice that the pattern breaks when the first function is
"monadic":
q)h:neg *
q)h[2;3]
'rank
[0] h[2;3]
^
Also here:
q)i:neg neg
'type
[0] i:neg neg
^
At this point, my intuition is that this pattern only applies when we are
interested on composing dyadic standard (vs user-defined) operators that exploit infix
notation. Am I getting it right? Is this syntactic sugar actually more general? Is there any
documentation where the pattern is fully described? Thanks!
There are some documented ways to achieve what you wish:
https://code.kx.com/q/ref/apply/#composition
You can create a unary train using #
q)r:neg neg#
q)r 1
1
https://code.kx.com/q/ref/compose/
You can use ' to compose a unary value with another of rank >=1
q)f:('[1+;*])
q)f[2;3]
7
Likely the behaviour you are seeing is not officially there to be exploited by users in q so should not be relied upon. This link may be of interest:
https://github.com/quintanar401/DCoQ
Right example:
"Hello".foldLeft(1L)((a, b) => a * b)
REPL prints errors:
"Hello" foldLeft(1L)((a, b) => a * b)
How is it explained? Is there some rule? I red that it is good to skip dots in Scala, but some examples don't work.
error: Long(1L) does not take parameters "Hello" foldLeft(1L)((a, b)
=> a * b)
You can use "infix notation" with methods of Arity-1 (single parameter). The convention is to use these for purely-functional methods. With curried functions (multiple parameter lists) like foldLeft, you can only use infix notation against the first parameter list (which would be confusing and you probably don't want to do this).
Related:
What are the precise rules for when you can omit parenthesis, dots, braces, = (functions), etc.?
The documentation:
http://docs.scala-lang.org/style/method-invocation
With curried functions:
Curried method call by infix notation
foldLeft is a curried function, and curried functions are non-intuitive to use with infix (dotless) notation. You need to wrap the infix call in parenthesis, like this:
scala> ("Hello" foldLeft 1L)((a, b) => a * b)
res0: Long = 9415087488
In this case, I would advise against this kind of usage.
For some general rules, you can look at the style guide.
I practicing in swift's playground and I couldn't figure out why swift is too specific about where programmer should provide spaces and where not. I asked this question on many sites and chatrooms but didn't got any answer.
var j: Int = 34 // Right
var j:Int=23 //Wrong
Also, In class
self.variable-= 5 //Wrong. Error: Consecutive statements must be followed by ;
self.variable-=5 // Right
self.variable -= 5 // Right
;
Even this ":" creates some issues with spaces sometimes.
I think spaces should have absolutely no effect on the code. It's usually just for a programmer's benefit. It just makes the code more readable nothing else. What's the best resource to read all swift rules about spaces.
Answer to the second part of your question can be found here swift docs
The whitespace around an operator is used to determine whether an operator is used as a prefix operator, a postfix operator, or a binary operator. This behavior is summarized in the following rules:
If an operator has whitespace around both sides or around neither side, it is treated as a binary operator. As an example, the + operator in a+b and a + b is treated as a binary operator.
If an operator has whitespace on the left side only, it is treated as a prefix unary operator. As an example, the ++ operator in a ++b is treated as a prefix unary operator.
If an operator has whitespace on the right side only, it is treated as a postfix unary operator. As an example, the ++ operator in a++ b is treated as a postfix unary operator.
If an operator has no whitespace on the left but is followed immediately by a dot (.), it is treated as a postfix unary operator. As an example, the ++ operator in a++.b is treated as a postfix unary operator (a++ .b rather than a ++ .b).
etc... (read the docs for more on this)
As for the first part of your question, I didn't see any issue with either way of declaring the variables.
var j: Int = 34
var j:Int=23
The only issue with that provided code is that you declare j twice in the same scope. Try changing one of the j's to an x or y or something else.
If you were wondering about
var j:Int =10
or
var j:Int= 10
look at the rules above. = is an operator so if you were to do either of those, it would be treated as prefix or postfix, and you would get the error that prefix/postfix = is reserved
These rules are important due to the existence of operators such as the unary plus and unary minus operators. The compiler needs to be able to distinguish between a binary plus and a unary plus operator. List of operators
I nearly talked about
35.+(10)
as an example of postfix notation because I understood
35 + 10
to be infix notation (at least everyone talks about that as an example of infix notation). But that's wrong isn't it?
35 10 +
would be postfix.
So how do I distinguish between the first two examples by name? Are they both "infix" but the second just a neater way?
Indeed it is still "infix".
Postfix means that all operands to an operator come in the stream before the operator itself. (an example is the factorial "!" operator in mathematics)
Prefix means the operator comes before the operands (an example is the "negate"/"-" operator to make a number negative).
Infix simply means that the operator is somewhere between the operands.
To decide how to name the application syntax, break the fragment up into tokens.
35.+(10)
is
[35] [.] [+] [(] [10] [)]
dropping the redundant parens, and let's name '.' as 'apply' we get:
[35] [apply] [+] [10]
So it most certainly is infix, as the binary operator is between the first and second argument.
It's just a bit noisy for what is also written as 35 + 10
I have a statement which currently looks like this:
arrays.foldLeft(0)((offset, array) => array.copyTo(largerArray, offset))
It would be great to express it as follows, but this is not possible since foldLeft is designed to take the seed argument first:
arrays.foldLeft(0)(_.copyTo(largerArray, _))
This is purely superficial - I'm just curious!
p.s. copyTo returns the next offset in this example.
The SLS seems to say "no".
Section 6.23, Anonymous Functions/Placeholder Syntax for Anonymous Functions:
An expression (of syntactic category Expr) may contain embedded
underscore symbols _ at places where identifiers are legal. Such an
expression represents an anonymous function where subsequent
occurrences of underscores denote successive parameters.
and
If an expression e binds underscore sections u1 , . . . , un, in this order, it is equivalent to the anonymous function (u'1 , ... u'n ) => e' where each u'i results from ui by replacing the
underscore with a fresh identifier and e' results from e by
replacing each underscore section ui by u'i.
Emphasis is mine - it explicitly states in both relevant section that a preserved ordering is assumed.
Personally, I think it makes sense to enforce that, if "only" for readability reasons.