While going through the book Scala for the Impatient, I came across this question:
Come up with one situation where the assignment x = y = 1 is valid in
Scala. (Hint: Pick a suitable type for x.)
I am not sure what exactly the author means by this question. The assignment doesn't return a value, so something like var x = y = 1 should return Unit() as the value of x. Can somebody point out what might I be missing here?
Thanks
In fact, x is Unit in this case:
var y = 2
var x = y = 1
can be read as:
var y = 2
var x = (y = 1)
and finally:
var x: Unit = ()
You can get to the point of being able to type x=y=1 in the REPL shell with no error thus:
var x:Unit = {}
var y = 0
x = y = 1
Here’s another less known case where the setter method returns its argument. Note that the type of x is actually Int here:
object AssignY {
private var _y: Int = _
def y = _y
def y_=(i: Int) = { _y = i; i }
}
import AssignY._
var x = y = 1
(This feature is used in the XScalaWT library, and was discussed in that question.)
BTW if assigning of the same value to both variables still required then use:
scala> var x#y = 1
x: Int = 1
y: Int = 1
It's valid, but not sensible, this make confusion.
scala> var x=y=1
x: Unit = ()
scala> y
res60: Int = 1
scala> var x#y = 1
x: Int = 1
y: Int = 1
Related
I understand how lazy variable works but I don't know how to implement properly.
Below is just an example:
func calculation() -> (firstValue: Float, secondValue: Float) {
var a: Float = 2
var b: Float = 2
for i in 1...1000 {
a = a + Float(i)
b = b + Float(i)
print(i)
}
return (a, b)
}
let m = calculation().firstValue
let n = calculation().secondValue
when I run it, the calculation function ran twice (1000 time + 1000 time), first time to get the value to m, and second time to get the value of n.
What I have to do to force the function Calculation to run just only not time and to store the value m and n without repeat the process twice.
The lazy keyword is used on the class/struct/enum member variables.
For your example, you can implement like this:
class Solution {
lazy var tuple: (firstValue: Float, secondValue: Float) = {
var a: Float = 2
var b: Float = 2
for i in 1...1000 {
a = a + Float(i)
b = b + Float(i)
print(i)
}
return (a, b)
}()
}
let s = Solution()
let m = s.tuple.firstValue
let n = s.tuple.firstValue
The tuple variable stores the value returned by the following closure which only runs once.
You can also use a variable to record the return value of the function.
let pair = calculation()
let m = pair.firstValue
let n = pair.secondValue
lazy is the keyword to delay the calculation till the result is first used, so it is not for your case.
You can write something like this:
let values = calculation()
let m: Float = values.firstValue
let n: Float = values.secondValue
Or this:
let (m, n) = calculation()
My code is returning 2 errors, both are unresolved identifiers. I looked up what means and most query answers are saying that I need to declare the constant first, but I have already done that.
I'm very new to coding and everytime I encountered this problem it was because I forgot to declare the constant or variable and I would catch my mistake but I'm stumped on this one.
var counter = 2
func fibonacci(_ x:Int ) -> Int {
var a = 1
var b = 1
if counter < x {
let sum = a + b
a = b
b = sum
counter += 1
}
print(sum)
return sum
}
fibonacci(5)
I bet you'll want to define counter within the scope of your function (passing it as a parameter might not make sense) and then define sum outside the scope of the if statement like this:
func fibonacci(_ x:Int ) -> Int {
var a = 1
var b = 1
var sum = 0
var counter = 0
if counter < x {
sum = a + b
a = b
b = sum
counter += 1
}
print(sum)
return sum
}
You've declared the variable sum inside the if condition and using it outside the if condition.
Return b instead of sum at the end of the function. Your if block will be executed only once. You should use while loop
var counter = 2
func fibonacci(_ x:Int ) -> Int {
var a = 1
var b = 1
while counter < x {
let sum = a + b
a = b
b = sum
counter += 1
}
print(b)
return b
}
print(fibonacci(5))
You can simplify the swapping using a tuple
var counter = 2
func fibonacci(_ x:Int ) -> Int {
var a = 1
var b = 1
while counter < x {
(a,b) = (b,a+b)
counter += 1
}
print(b)
return b
}
print(fibonacci(5))
var counter = 2
func fibonacci(_ x:Int ) -> Int {
var a = 1
var b = 1
var sum = 0 //this is when if you want to add sum
//var counter = 0 if you may please work around the counter
if counter < x {
sum = a + b
a = b
b = sum
counter += 1
}
return sum //if you declare sum then return sum could be used
}
var x = fibonacci(5)//here the return value is stored or used for further computations
print(x) // the returned value can be printed in this way or directly print(fibonacci(5))
If you feel like learning it more please go through following link https://docs.swift.org/swift-book/LanguageGuide/Functions.html
The code above is not a solution to fibonacci series but a solution to your error. Fibonacci series can be solved in many ways using logic. As your question is only for the errors the program above solves it. If you feel like studying it using algorithms please checkout this link: https://www.codewithc.com/fibonacci-series-algorithm-flowchart/
I hope the answer helps!
The unresolved indentifiers errors is because neither counter or sum are variables defined.
Just define them, Eg:
var sum = 0;
func fibonacci(counter: Int, x:Int) -> Int {
var a = 1
var b = 1
if counter < x {
sum = a + b;
a = b
b = sum
return fibonacci(counter: counter + 1, x: x)
}
return sum
}
fibonacci(counter: 0, x: 5)
Note: the fibonacci func is not working properly but the identified errors were solved.
I try to implement a version of the Monte Carlo algorithm in Scala but i have a little problem.
In my first loop, i have a mismatch with Unit and Int, but I didn't know how to slove this.
Thank for your help !
import scala.math._
import scala.util.Random
import scala.collection.mutable.ListBuffer
object Main extends App{
def MonteCarlo(list: ListBuffer[Int]): List[Int] = {
for (i <- list) {
var c = 0.00
val X = new Random
val Y = new Random
for (j <- 0 until i) {
val x = X.nextDouble // in [0,1]
val y = Y.nextDouble // in [0,1]
if (x * x + y * y < 1) {
c = c + 1
}
}
c = c * 4
var p = c / i
var error = abs(Pi-p)
print("Approximative value of pi : $p \tError: $error")
}
}
var liste = ListBuffer (200, 2000, 4000)
MonteCarlo(liste)
}
A guy working usually with Python.
for loop does not return anything, so that's why your method returns Unit but expects List[Int] as return type is List[Int].
Second, you have not used scala interpolation correctly. It won't print the value of error. You forgot to use 's' before the string.
Third thing, if want to return list, you first need a list where you will accumulate all values of every iteration.
So i am assuming that you are trying to return error for all iterations. So i have created an errorList, which will store all values of error. If you want to return something else you can modify your code accordingly.
def MonteCarlo(list: ListBuffer[Int]) = {
val errorList = new ListBuffer[Double]()
for (i <- list) {
var c = 0.00
val X = new Random
val Y = new Random
for (j <- 0 until i) {
val x = X.nextDouble // in [0,1]
val y = Y.nextDouble // in [0,1]
if (x * x + y * y < 1) {
c = c + 1
}
}
c = c * 4
var p = c / i
var error = abs(Pi-p)
errorList += error
println(s"Approximative value of pi : $p \tError: $error")
}
errorList
}
scala> MonteCarlo(liste)
Approximative value of pi : 3.26 Error: 0.11840734641020667
Approximative value of pi : 3.12 Error: 0.02159265358979301
Approximative value of pi : 3.142 Error: 4.073464102067881E-4
res9: scala.collection.mutable.ListBuffer[Double] = ListBuffer(0.11840734641020667, 0.02159265358979301, 4.073464102067881E-4)
I am reading a book in scala and one of the exercises is as follows:
Come up with one situation where the assignment x = y = 1 is valid in Scala. (Hint: Pick a suitable type for x.)
The 2 solutions I could come up with are:
val x, y : Int = 1
val x, y = (1, 2)
Have I missed another way that the exercise is looking for?
"valid" and "useful" don't necessarily mean the same thing :)
scala> var y = 2
y: Int = 2
scala> val x = y = 1
x: Unit = ()
scala>
Simple scala question. Consider the below.
scala> var mycounter: Int = 0;
mycounter: Int = 0
scala> mycounter += 1
scala> mycounter
res1: Int = 1
In the second statement I increment my counter. But nothing is returned. How do I increment and return something in one statement.
Using '+=' return Unit, so you should do:
{ mycounter += 1; mycounter }
You can too do the trick using a closure (as function parameters are val):
scala> var x = 1
x: Int = 1
scala> def f(y: Int) = { x += y; x}
f: (y: Int)Int
scala> f(1)
res5: Int = 2
scala> f(5)
res6: Int = 7
scala> x
res7: Int = 7
BTW, you might consider using an immutable value instead, and embrace this programming style, then all your statements will return something ;)
Sometimes I do this:
val nextId = { var i = 0; () => { i += 1; i} }
println(nextId()) //> 1
println(nextId()) //> 2
Might not work for you if you need sometime to access the value without incrementing.
Assignment is an expression that is evaluated to Unit. Reasoning behind it can be found here: What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?
In Scala this is usually not a problem because there probably is a different construct for the problem you are solving.
I don't know your exact use case, but if you want to use the incrementation it might be in the following form:
(1 to 10).foreach { i =>
// do something with i
}