I know that scala allows overloading for it's default operators (+, - ! etc.) . Is it possible to define custom operators and make something like the |.| operator so that | -3| that evaluates to 3. Or defining an operator like ++++ so that a ++++ b equals a+3*b?
You should look at scala operators documentation.
You can easily make the ++++ operator but not the |.| operator.
Operators in scala are just functions with non alphanumeric name. Since scala also support call a.f(b) as a f b then you can achieve the first behavior. For example:
case class A(v: Int) {
def ++++(b: A): A = A(v + 3 * b.v)
}
val a = A(1)
val b = A(2)
a ++++ b
>> A(7)
a.++++(b) // just another way of doing the exact same call
If you want to add this to integer you would simply create an implicit class to add it.
Another option is to prefix the operator for example consider doing -a to get the negative. There is no "first element" to apply the - to, instead - is applied to a (see this answer).
For example:
case class A(v: Int) {
def unary_!(): Int = -v
}
val a = A(3)
!a
>> -3
Doing |.| has two issues: First there are two parts to the operator, i.e. it is split. The second is the use of |
In order to do a two part operator (say !.!) you would probably want to generate some private type and return it from one ! and then use it as the input for the other to return the output type.
The second issue is the use of | which is an illegal character. Look at this answer for a list of legal characters
An example to extend #assaf-mendelson answer
case class Abs(a: Int) {
def !(): Int = a.abs
}
implicit def toAbs(a: Int) = new {
def unary_! : Abs = Abs(a)
}
then
> val a = -3
a: Int = -3
> !a
res0: Abs = Abs(-3)
> !a!
res1: Int = 3
> val b = 12
b: Int = 12
> !b!
res2: Int = 12
> (!a!) + (!b!)
res3: Int = 15
We cannot implement abs as |a| because unary_ works only with !, ~, + and -
Related
In the following statement the val f is defined as a lambda that references itself (it is recursive):
val f: Int => Int = (a: Int) =>
if (a > 10) 3 else f(a + 1) + 1 // just some simple function
I've tried it in the REPL, and it compiles and executes correctly.
According to the specification, this seems like an instance of illegal forward referencing:
In a statement sequence s[1]...s[n] making up a block, if a simple
name in s[i] refers to an entity defined by s[j] where j >= i,
then for all s[k] between and including s[i] and s[j],
s[k] cannot be a variable definition.
If s[k] is a value definition, it must be lazy.
The assignment is a single statement, so it satisfied the j >= i criteria, and it is included in the interval of statements the two rules apply to (between and including s[i] and s[j]).
However, it seems that it violates the second rule, because f is not lazy.
How is that a legal statement (tried it in Scala 2.9.2)?
You probably tried to use this in the REPL, which wraps all contents in an object definition. This is important because in Scala (or better: on the JVM) all instance values are initialized with a default value, which is null for all AnyRefs and 0, 0.0 or false for AnyVals. For method values this default initialization does not happen, therefore you get an error message in this case:
scala> object x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
defined object x
scala> def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
<console>:7: error: forward reference extends over definition of value f
def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
^
This behavior can even lead to weird situations, therefore one should be careful with recursive instance values:
scala> val m: Int = m+1
m: Int = 1
scala> val s: String = s+" x"
s: String = null x
In OCaml, the let...in expression allows you to created a named local variable in an expression rather than a statement. (Yes I know that everything is technically an expression, but Unit return values are fairly useless.) Here's a quick example in OCaml:
let square_the_sum a b = (* function definition *)
let sum = a + b in (* declare a named local called sum *)
sum * sum (* return the value of this expression *)
Here's what I would want the equivalent Scala to look like:
def squareTheSum(a: Int, b: Int): Int =
let sum: Int = a + b in
sum * sum
Is there anything in Scala that I can use to achieve this?
EDIT:
You learn something new every day, and this has been answered before.
object ForwardPipeContainer {
implicit class ForwardPipe[A](val value: A) extends AnyVal {
def |>[B](f: A => B): B = f(value)
}
}
import ForwardPipeContainer._
def squareTheSum(a: Int, b: Int): Int = { a + b } |> { sum => sum * sum }
But I'd say that is not nearly as easy to read, and is not as flexible (it gets awkward with nested lets).
You can nest val and def in a def. There's no special syntax; you don't need a let.
def squareTheSum(a: Int, b: Int): Int = {
val sum = a + b
sum * sum
}
I don't see the readability being any different here at all. But if you want to only create the variable within the expression, you can still do that with curly braces like this:
val a = 2 //> a : Int = 2
val b = 3 //> b : Int = 3
val squareSum = { val sum = a + b; sum * sum } //> squareSum : Int = 25
There is no significant difference here between a semicolon and the word "in" (or you could move the expression to the next line, and pretend that "in" is implied if it makes it more OCaml-like :D).
val squareSum = {
val sum = a + b // in
sum * sum
}
Another, more technical, take on this: Clojure's 'let' equivalent in Scala. I think the resulting structures are pretty obtuse compared to the multi-statement form.
I'm having trouble understanding underscores in function literals.
val l = List(1,2,3,4,5)
l.filter(_ > 0)
works fine
l.filter({_ > 0})
works fine
l.filter({val x=1; 1+_+3 > 0}) // ie you can have multiple statements in your function literal and use the underscore not just in the first statement.
works fine
And yet:
l.filter({val x=_; x > 0})
e>:1: error: unbound placeholder parameter
l.filter({val x=_; x > 0})
I can't assign the _ to a variable, even though the following is legal function literal:
l.filter(y => {val x=y; x > 0})
works fine.
What gives? Is my 'val x=_' getting interpreted as something else? Thanks!
Actually, you have to back up a step.
You are misunderstanding how the braces work.
scala> val is = (1 to 5).toList
is: List[Int] = List(1, 2, 3, 4, 5)
scala> is map ({ println("hi") ; 2 * _ })
hi
res2: List[Int] = List(2, 4, 6, 8, 10)
If the println were part of the function passed to map, you'd see more greetings.
scala> is map (i => { println("hi") ; 2 * i })
hi
hi
hi
hi
hi
res3: List[Int] = List(2, 4, 6, 8, 10)
Your extra braces are a block, which is some statements followed by a result expression. The result expr is the function.
Once you realize that only the result expr has an expected type that is the function expected by map, you wouldn't think to use underscore in the preceding statements, since a bare underscore needs the expected type to nail down what the underscore means.
That's the type system telling you that your underscore isn't in the right place.
Appendix: in comments you ask:
how can I use the underscore syntax to bind the parameter of a
function literal to a variable
Is this a "dumb" question, pardon the expression?
The underscore is so you don't have to name the parameter, then you say you want to name it.
One use case might be: there are few incoming parameters, but I'm interested in naming only one of them.
scala> (0 /: is)(_ + _)
res10: Int = 15
scala> (0 /: is) { case (acc, i) => acc + 2 * i }
res11: Int = 30
This doesn't work, but one may wonder why. That is, we know what the fold expects, we want to apply something with an arg. Which arg? Whatever is left over after the partially applied partial function.
scala> (0 /: is) (({ case (_, i) => _ + 2 * i })(_))
or
scala> (0 /: is) (({ case (_, i) => val d = 2 * i; _ + 2 * d })(_))
SLS 6.23 "placeholder syntax for anonymous functions" mentions the "expr" boundary for when you must know what the underscore represents -- it's not a scope per se. If you supply type ascriptions for the underscores, it will still complain about the expected type, presumably because type inference goes left to right.
The underscore syntax is mainly user for the following replacement:
coll.filter(x => { x % 2 == 0});
coll.filter(_ % 2 == 0);
This can only replace a single parameter. This is the placeholder syntax.
Simple syntactic sugar for a lambda.
In the breaking case you are attempting null initialization/defaulting.
For primitive types with init conventions:
var x: Int = _; // x will be 0
The general case:
var y: List[String] = _; // y is null
var z: Any = _; // z = null;
To get pedantic, it works because null is a ref to the only instance of scala.Null, a sub-type of any type, which will always satisfy the type bound because of covariance. Look HERE.
A very common usage scenario, in ScalaTest:
class myTest extends FeatureTest with GivenWhenThen with BeforeAndAfter {
var x: OAuthToken = _;
before {
x = someFunctionThatReturnsAToken;
}
}
You can also see why you shouldn't use it with val, since the whole point is to update the value after initialization.
The compiler won't even let you, failing with: error: unbound placeholder parameter.
This is your exact case, the compiler thinks you are defaulting, a behaviour undefined for vals.
Various constraints, such as timing or scope make this useful.
This is different from lazy, where you predefine the expression that will be evaluated when needed.
For more usages of _ in Scala, look HERE.
Because in this two cases underscore (_) means two different things. In case of a function it's a syntactic sugar for lambda function, your l.filter(_ > 0) later desugares into l.filter(x => x > 0). But in case of a var it has another meaning, not a lambda function, but a default value and this behavior is defined only for var's:
class Test {
var num: Int = _
}
Here num gonna be initialized to its default value determined by its type Int. You can't do this with val cause vals are final and if in case of vars you can later assign them some different values, with vals this has no point.
Update
Consider this example:
l filter {
val x = // compute something
val z = _
x == z
}
According to your idea, z should be bound to the first argument, but how scala should understand this, or you you have more code in this computation and then underscore.
Update 2
There is a grate option in scala repl: scala -Xprint:type. If you turn it on and print your code in (l.filter({val x=1; 1+_+3 > 0})), this what you'll see:
private[this] val res1: List[Int] = l.filter({
val x: Int = 1;
((x$1: Int) => 1.+(x$1).+(3).>(0))
});
1+_+3 > 0 desugares into a function: ((x$1: Int) => 1.+(x$1).+(3).>(0)), what filter actually expects from you, a function from Int to Boolean. The following also works:
l.filter({val x=1; val f = 1+(_: Int)+3 > 0; f})
cause f here is a partially applied function from Int to Boolean, but underscore isn't assigned to the first argument, it's desugares to the closes scope:
private[this] val res3: List[Int] = l.filter({
val x: Int = 1;
val f: Int => Boolean = ((x$1: Int) => 1.+((x$1: Int)).+(3).>(0));
f
});
I have a graph, with each vertex connected to 6 neighbors.
While constructing the graph and making declarations of the connections, I would like to use a syntax like this:
1. val vertex1, vertex2 = new Vertex
2. val index = 3 // a number between 0 and 5
3. vertex1 + index = vertex2
The result should be that vertex2 be declared assigned as index-th neighbor of vertex1, equivalent to:
4. vertex1.neighbors(index) = vertex2
While frobbing with the implementation of Vertex.+, I came up with the following:
5. def +(idx: Int) = neighbors(idx)
which, very surprisingly indeed, did not cause line 3 to be underlined red by my IDE (IntelliJIdea, BTW).
However, compilation of line 3 offsprang the following message:
error: missing arguments for method + in class Vertex;
follow this method with `_' if you want to treat it as a partially applied function
Next, I tried with an extractor, but actually, that doesn't seem to fit the case very well.
Does anybody have any clue if what I'm trying to achieve is anywhat feasible?
Thank you
You probably can achieve what you want by using := instead of =. Take a look at this illustrating repl session:
scala> class X { def +(x:X) = x; def :=(x:X) = x }
defined class X
scala> val a = new X;
a: X = X#7d283b68
scala> val b = new X;
b: X = X#44a06d88
scala> val c = new X;
c: X = X#fb88599
scala> a + b := c
res8: X = X#fb88599
As one of the comments stated, the custom = requires two parameter, for example vertex1(i)=vertex2 is dessugared to vertext.update(i,vertex2) thus forbidding the exact syntax you proposed. On the other hand := is a regular custom operator and a:=b will dessugar to a.:=(b).
Now we still have one consideration to do. Is the precedence going to work as you intent? The answer is yes, according to the Language Specification section 6.12.3. + has higher precedence than :=, so it ends up working as (a+b):=c.
Not exactly what you want, just playing with right-associativity:
scala> class Vertex {
| val neighbors = new Array[Vertex](6)
| def :=< (n: Int) = (this, n)
| def >=: (conn: (Vertex, Int)) {
| val (that, n) = conn
| that.neighbors(n) = this
| this.neighbors((n+3)%6) = that
| }
| }
defined class Vertex
scala> val a, b, c, d = new Vertex
a: Vertex = Vertex#c42aea
b: Vertex = Vertex#dd9f68
c: Vertex = Vertex#ca0c9
d: Vertex = Vertex#10fed2c
scala> a :=<0>=: b ; a :=<1>=: c ; d :=<5>=: a
scala> a.neighbors
res25: Array[Vertex] = Array(Vertex#dd9f68, Vertex#ca0c9, Vertex#10fed2c, null, null, null)
I know that you can do matching on lists in a way like
val list = List(1,2,3)
list match {
case head::tail => head
case _ => //whatever
}
so I started to wonder how this works. If I understand correctly, :: is just an operator, so what's to stop me from doing something like
4 match {
case x + 2 => x //I would expect x=2 here
}
If there is a way to create this kind of functionality, how is it done; if not, then why?
Pattern matching takes the input and decomposes it with an unapply function. So in your case, unapply(4) would have to return the two numbers that sum to 4. However, there are many pairs that sum to 4, so the function wouldn't know what to do.
What you need is for the 2 to be accessible to the unapply function somehow. A special case class that stores the 2 would work for this:
case class Sum(addto: Int) {
def unapply(i: Int) = Some(i - addto)
}
val Sum2 = Sum(2)
val Sum2(x) = 5 // x = 3
(It would be nice to be able to do something like val Sum(2)(y) = 5 for compactness, but Scala doesn't allow parameterized extractors; see here.)
[EDIT: This is a little silly, but you could actually do the following too:
val `2 +` = Sum(2)
val `2 +`(y) = 5 // y = 3
]
EDIT: The reason the head::tail thing works is that there is exactly one way to split the head from the tail of a list.
There's nothing inherently special about :: versus +: you could use + if you had a predetermined idea of how you wanted it to break a number. For example, if you wanted + to mean "split in half", then you could do something like:
object + {
def unapply(i: Int) = Some(i-i/2, i/2)
}
and use it like:
scala> val a + b = 4
a: Int = 2
b: Int = 2
scala> val c + d = 5
c: Int = 3
d: Int = 2
EDIT: Finally, this explains that, when pattern matching, A op B means the same thing as op(A,B), which makes the syntax look nice.
Matching with case head :: tail uses an infix operation pattern of the form p1 op p2 which gets translated to op(p1, p2) before doing the actual matching. (See API for ::)
The problem with + is the following:
While it is easy to add an
object + {
def unapply(value: Int): Option[(Int, Int)] = // ...
}
object which would do the matching, you may only supply one result per value. E.g.
object + {
def unapply(value: Int): Option[(Int, Int)] = value match {
case 0 => Some(0, 0)
case 4 => Some(3, 1)
case _ => None
}
Now this works:
0 match { case x + 0 => x } // returns 0
also this
4 match { case x + 1 => x } // returns 3
But this won’t and you cannot change it:
4 match { case x + 2 => x } // does not match
No problem for ::, though, because it is always defined what is head and what is tail of a list.
There are two ::s (pronounced "cons") in Scala. One is the operator on Lists and the other is a class, which represents a non empty list characterized by a head and a tail. So head :: tail is a constructor pattern, which has nothing to do with the operator.