Say I have some function like this:
def doSomeCode(code: => Unit): Unit = {
println("Doing some code!")
code
}
It takes in a function, prints out "Doing some code!" and then calls the passed function. If for example we called it like:
doSomeCode {
println("Some code done!")
}
It would print out "Doing some code!", followed by "Some code done!".
But I would like to disallow the use of outside variables inside that code block, for example:
def otherFunction(): Unit = {
val number = 10
doSomeCode{
println("The number is " + number)
}
}
This will print out "Doing some code!", followed by "The number is 10". But I would like it to instead throw an error because I do not want number to be in the scope of doSomeCode. Is this possible to achieve in Scala?
To be clear I am not asking if this is a good idea, I just want to know if it is possible.
Edit:
The reason I want this is because I am trying to make a syntax that is perfectly functional, I want a block with no side effects. Ideally the syntax would look like:
val a = 1
val b = 2
val c = 3
val d = 4
val sum = use(a, c, d){
val total = a + c + d
total
}
This way I as a programmer know that the only variables used are a, c, and d and that sum is the only output. Trying to use anything else, eg b, would result in an error. Currently it is not possible to know at a glance what variables a block is using. I can achieve this by just making and using a function like this:
def example(): Unit = {
val a = 1
val b = 2
val c = 3
val d = 4
val sum = sum(a, c, d)
}
def sum(a: Int, b: Int, c: Int): Int = {
val total = a + b + c
total
}
This behaves exactly like how I want it to, but I would like it to be inline with the other code, not outside as an external function.
scala> def mkClosure(i: Int) = { s: String => s"$i - $s" }
mkClosure: (i: Int)String => String
scala> mkClosure(5)
res0: String => String = <function1>
Since whether the function depends on values which aren't parameters isn't encoded in the type system, there's no compiler-enforceable difference in Scala between such a function and a pure one. It's unlikely to be possible with macros: a compiler plugin is probably your best bet, especially if you want to allow certain values (e.g. println) to be used inside a block.
This is perhaps a half-baked idea, but can I copy the environment of an expression? Consider the following example:
class foo[T](block: => T) {
var data = { () => block }
def run() = { data() }
}
var a = 5
var b = new foo({ a += 1; println(a) })
var c = new foo({ a += 1; println(a) })
b.run()
c.run()
b.run()
c.run()
I get the following output:
6
7
8
9
But what I really want is the following:
6
6
7
7
In short, I want foo to have copies of the variables in the block instead of referring to them, once the initial value has been resolved. Can this be done? scala.util.DynamicVariable seems promising, but I'm having a hard time understanding how I might use it in the example above.
If you want to make a copy, then why not make a copy?
var c = new foo({ var aa = a + 1; println(aa) })
If you want to take an existing closure that refers to a variable, and turn it into a closure that refers to a copy of that variable, then I'm afraid it's not possible.
In any case, mutable variables should not be used except in very rare circumstances and in a very controlled manner. That is, not juggling their references.
I think your problem is that you're closing over a (and thus changing its value as your program runs), rather than closing over a different variable initialized from a. You might want to try something more like this:
class bar[T](block: (T) => T, a: T) {
var cur = a
def run() = { cur = block(cur); cur }
}
var a = 5
var b = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
var c = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
b.run()
c.run()
b.run()
c.run()
Output:
6
6
7
7
However, note that unlike your code, this will not affect the value of the a variable as it runs.
1) As n.m. already mentioned, you should prefer immutable concepts when using closures.
2) On the other hand this is exactly what closures are for. They don't capture the value of the variabe, they capture the variable itself! Your question is kinda upside-down. You actually are capturing the environment - the environment of your variable. If you don't need the same variable than copy it as n.m. or Ian McLaird respectively suggested.
Is there any reason for Scala not support the ++ operator to increment primitive types by default?
For example, you can not write:
var i=0
i++
Thanks
My guess is this was omitted because it would only work for mutable variables, and it would not make sense for immutable values. Perhaps it was decided that the ++ operator doesn't scream assignment, so including it may lead to mistakes with regard to whether or not you are mutating the variable.
I feel that something like this is safe to do (on one line):
i++
but this would be a bad practice (in any language):
var x = i++
You don't want to mix assignment statements and side effects/mutation.
I like Craig's answer, but I think the point has to be more strongly made.
There are no "primitives" -- if Int can do it, then so can a user-made Complex (for example).
Basic usage of ++ would be like this:
var x = 1 // or Complex(1, 0)
x++
How do you implement ++ in class Complex? Assuming that, like Int, the object is immutable, then the ++ method needs to return a new object, but that new object has to be assigned.
It would require a new language feature. For instance, let's say we create an assign keyword. The type signature would need to be changed as well, to indicate that ++ is not returning a Complex, but assigning it to whatever field is holding the present object. In Scala spirit of not intruding in the programmers namespace, let's say we do that by prefixing the type with #.
Then it could be like this:
case class Complex(real: Double = 0, imaginary: Double = 0) {
def ++: #Complex = {
assign copy(real = real + 1)
// instead of return copy(real = real + 1)
}
The next problem is that postfix operators suck with Scala rules. For instance:
def inc(x: Int) = {
x++
x
}
Because of Scala rules, that is the same thing as:
def inc(x: Int) = { x ++ x }
Which wasn't the intent. Now, Scala privileges a flowing style: obj method param method param method param .... That mixes well C++/Java traditional syntax of object method parameter with functional programming concept of pipelining an input through multiple functions to get the end result. This style has been recently called "fluent interfaces" as well.
The problem is that, by privileging that style, it cripples postfix operators (and prefix ones, but Scala barely has them anyway). So, in the end, Scala would have to make big changes, and it would be able to measure up to the elegance of C/Java's increment and decrement operators anyway -- unless it really departed from the kind of thing it does support.
In Scala, ++ is a valid method, and no method implies assignment. Only = can do that.
A longer answer is that languages like C++ and Java treat ++ specially, and Scala treats = specially, and in an inconsistent way.
In Scala when you write i += 1 the compiler first looks for a method called += on the Int. It's not there so next it does it's magic on = and tries to compile the line as if it read i = i + 1. If you write i++ then Scala will call the method ++ on i and assign the result to... nothing. Because only = means assignment. You could write i ++= 1 but that kind of defeats the purpose.
The fact that Scala supports method names like += is already controversial and some people think it's operator overloading. They could have added special behavior for ++ but then it would no longer be a valid method name (like =) and it would be one more thing to remember.
I think the reasoning in part is that +=1 is only one more character, and ++ is used pretty heavily in the collections code for concatenation. So it keeps the code cleaner.
Also, Scala encourages immutable variables, and ++ is intrinsically a mutating operation. If you require +=, at least you can force all your mutations to go through a common assignment procedure (e.g. def a_=).
The primary reason is that there is not the need in Scala, as in C. In C you are constantly:
for(i = 0, i < 10; i++)
{
//Do stuff
}
C++ has added higher level methods for avoiding for explicit loops, but Scala has much gone further providing foreach, map, flatMap foldLeft etc. Even if you actually want to operate on a sequence of Integers rather than just cycling though a collection of non integer objects, you can use Scala range.
(1 to 5) map (_ * 3) //Vector(3, 6, 9, 12, 15)
(1 to 10 by 3) map (_ + 5)//Vector(6, 9, 12, 15)
Because the ++ operator is used by the collection library, I feel its better to avoid its use in non collection classes. I used to use ++ as a value returning method in my Util package package object as so:
implicit class RichInt2(n: Int)
{
def isOdd: Boolean = if (n % 2 == 1) true else false
def isEven: Boolean = if (n % 2 == 0) true else false
def ++ : Int = n + 1
def -- : Int = n - 1
}
But I removed it. Most of the times when I have used ++ or + 1 on an integer, I have later found a better way, which doesn't require it.
It is possible if you define you own class which can simulate the desired output however it may be a pain if you want to use normal "Int" methods as well since you would have to always use *()
import scala.language.postfixOps //otherwise it will throw warning when trying to do num++
/*
* my custom int class which can do ++ and --
*/
class int(value: Int) {
var mValue = value
//Post-increment
def ++(): int = {
val toReturn = new int(mValue)
mValue += 1
return toReturn
}
//Post-decrement
def --(): int = {
val toReturn = new int(mValue)
mValue -= 1
return toReturn
}
//a readable toString
override def toString(): String = {
return mValue.toString
}
}
//Pre-increment
def ++(n: int): int = {
n.mValue += 1
return n;
}
//Pre-decrement
def --(n: int): int = {
n.mValue -= 1
return n;
}
//Something to get normal Int
def *(n: int): Int = {
return n.mValue
}
Some possible test cases
scala>var num = new int(4)
num: int = 4
scala>num++
res0: int = 4
scala>num
res1: int = 5 // it works although scala always makes new resources
scala>++(num) //parentheses are required
res2: int = 6
scala>num
res3: int = 6
scala>++(num)++ //complex function
res4: int = 7
scala>num
res5: int = 8
scala>*(num) + *(num) //testing operator_*
res6: Int = 16
Of course you can have that in Scala, if you really want:
import scalaz._
import Scalaz._
case class IncLens[S,N](lens: Lens[S,N], num : Numeric[N]) {
def ++ = lens.mods(num.plus(_, num.one))
}
implicit def incLens[S,N:Numeric](lens: Lens[S,N]) =
IncLens[S,N](lens, implicitly[Numeric[N]])
val i = Lens[Int,Int](identity, (x, y) => y)
val imperativeProgram = for {
_ <- i := 0;
_ <- i++;
_ <- i++;
x <- i++
} yield x
def runProgram = imperativeProgram ! 0
And here you go:
scala> runProgram
runProgram: Int = 3
It isn't included because Scala developers thought it make the specification more complex while achieving only negligible benefits and because Scala doesn't have operators at all.
You could write your own one like this:
class PlusPlusInt(i: Int){
def ++ = i+1
}
implicit def int2PlusPlusInt(i: Int) = new PlusPlusInt(i)
val a = 5++
// a is 6
But I'm sure you will get into some trouble with precedence not working as you expect. Additionally if i++ would be added, people would ask for ++i too, which doesn't really fit into Scala's syntax.
Lets define a var:
var i = 0
++i is already short enough:
{i+=1;i}
Now i++ can look like this:
i(i+=1)
To use above syntax, define somewhere inside a package object, and then import:
class IntPostOp(val i: Int) { def apply(op: Unit) = { op; i } }
implicit def int2IntPostOp(i: Int): IntPostOp = new IntPostOp(i)
Operators chaining is also possible:
i(i+=1)(i%=array.size)(i&=3)
The above example is similar to this Java (C++?) code:
i=(i=i++ %array.length)&3;
The style could depend, of course.
I got the following code snippet referring an example in Chapter 6 of "Programming Scala":
object HelloWorld {
def main(args: Array[String]) {
trait AbstractT2 {
println("In AbstractT2:")
val value: Int
val inverse = 1.0 / value // ???
println("AbstractT2: value = " + value + ", inverse = " + inverse)
}
val c2b = new AbstractT2 {
println("In c2b:") //---->line 1
val value = 10 //---->line 2
}
println("c2b.value = " + c2b.value + ", inverse = " + c2b.inverse)
}
}
The result of the above code is:
In AbstractT2:
AbstractT2: value = 0, inverse = Infinity
In c2b:
c2b.value = 10, inverse = Infinity
Since the anonymous class initialization is after the trait initialization, the result is understandable. But if I exchange line 1 and line 2 in the above example, so that val value = 10 precedes println("In c2b:"), the result will be:
In AbstractT2:
AbstractT2: value = 10, inverse = 0.1
In c2b:
c2b.value = 10, inverse = 0.1
It seems this time the initialization is successful although it's wrong from language point of view. I can't understand why. Can anybody help on this? Thanks a lot.
Initialization semantics changed from 2.7 to 2.8. Here's the commit, way back in 2008. "HARD HATS ON!"
https://lampsvn.epfl.ch/trac/scala/changeset/16745
Up to 2.7 Scala moved value initializations in front of the superclass constructor
until an initialization which references this was encountered. There it would stop.
Much, much earlier, this behavior was necessary to get some composition patterns working. Later, we introduced early definitions to get the same patterns working in a more robust way.
But since the behavior was difficult to change it took us until 2.8 to actually do it.
I am looking to write a system which allows a syntax like the following:
a b/c
With a being a class, b being a specific term (not any arbitrary string) and c being an Int.
I realize you can do
a b c
which becomes
a.b(c)
However, the first syntax would be more elegant and any solution would help me expand my scala knowledge :)
If any of these is good enough for you...
a { b/c }
a ( b/c )
...this will do the trick:
trait Term { def / (n:Int):(Term,Int) = (this,n) }
case object Inc extends Term // any other terms declared likewise
and then your class could support it this way:
class A {
def apply(t:(Term,Int)) = t match {
case (Inc,n) => n + 1
// further term implementations
}
}
Usage:
scala> val a = new A
a: A = A#1c2628
scala> a { Inc / 8 }
res28: Int = 9
scala> a ( Inc / 8 )
res29: Int = 9