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.
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
I always thought that in q and in k all expressions divided ; evaluated left-to-right and operator precedence inside is right-to-left.
But then I tried to apply this principle to Ament At operator parameters. Confusingly it seems working in the opposite direction:
$ q KDB+ 3.6 2019.04.02 Copyright (C) 1993-2019 Kx Systems
q)#[10 20 30;g;:;100+g:1]
10 101 30
The same precedence works inside a function parameters too:
q){x+y}[q;10+q:100]
210
So why does it happend - why does it first calculate the last one parameter and only then first? Is it a feature we should avoid?
Upd: evaluation vs parsing.
There could be another cases: https://code.kx.com/q/ref/apply/#when-e-is-not-a-function
q)#[2+;"42";{)}]
')
[0] #[2+;"42";{)}]
q)#[string;42;a:100] / expression not a function
"42"
q)a // but a was assigned anyway
100
q)#[string;42;{b::99}] / expression is a function
"42"
q)b // not evaluated
'b
[0] b
^
The semicolon is a multi-purpose separator in q. It can separate statements (e.g. a:10; b:20), in which case statements are evaluated from left-to-right similar to many other languages. But when it separates elements of a list it creates a list expression which (an expression) is evaluated from right-to-left as any other q expression would be.
Like in this example:
q)(q;10+q:100)
110 100
One of many overloads of the dot operator (.) evaluates its left operand on a list of values in its right operand:
q){x+y} . (q;10+q:100)
210
In order to do so a list expression itself needs to be evaluated first, and it will be, from right-to-left as any other list expression.
However, the latter is just another way of getting the result of
{x+y}[q;10+q:100]
which therefore should produce the same value. And it does. By evaluating function arguments from right-to-left, of course!
A side note. Please don't be confused by the conditional evaluation statement $[a;b;c]. Even though it looks like an expression it is in fact a statement which evaluates a first and only then either b or c. In other words a, b and c are not arguments of some function $ in this case.
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.
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.
I'm learning Scala and lift at the same time and I got stuck on understanding the syntax used to inintialize the SiteMap in the Boot.scala:
val entries = Menu(Loc("Home", "/", "Home")) ::
Menu(Loc("Foo", "/badger", "Foo")) ::
Menu(Loc("Directory Foo", "/something/foo", "Directory Foo")) :: Nil
LiftRules.setSiteMap(SiteMap(entries:_*))
What exactly is the meaning of the SiteMap parameter?
I see that the value entries is a list of Menu. What is the colon, underscore, star?
At first I thought it is a method on the List, but I am unable to find such definition...
OK, after my colleague mentioned to me, that he encountered this secret incantation in the Programming in Scala book, I did a search in my copy and found it described in Section 8.8 Repeated parameters. (Though you need to search with space between the colon and underscore :-/ ) There is a one sentence to explain it as:
... append the array argument with a colon and an _* symbol, like this:
scala> echo(arr: _*)
This notation tells the compiler to pass each element of arr as its own argument to echo, rather than all of it as a single argument.
I find the description offered here more helpful.
So x: _* is like a type declaration that tells the compiler to treat x as repeated parameter (aka variable-length argument list — vararg).