How can I scope variables to have expressions with other variables in the same scope? I tried this but it doesn't work. I want c to equal b + 2 then I want to be able to get the result of any variable in the scope.
let scope = {
a: '= b + c',
b: 1,
c: 2
};
console.log(math.evaluate('a'), scope);
You can not evaluate c = 'b+2' inside scope you need to explicitly evaluate c scope
// provide a scope
let scope = {
a: 3,
b: 4
}
math.evaluate('c = b + 2', scope) // 6
scope.c // 6
Related
I have 3 variables that have already been initialized, and I want to assign a new value to all three of them. e.g.
var a = 1
var b = 2
var c = 3
and I want to reassign them to the same value e.g.
a = b = c = 4
But the above expression is invalid. Is there a right way to do this in Scala?
It is possible to slightly shorten the var definition code as follows
var (a, b, c) = (1, 2, 3)
This works because of extractor objects in scala. A tuple of 3 is extracted into 3 components it was created with.
But following does not work becase the extraction is applied on val or var definitions.
(a, b, c) = (4, 4, 4)
You can do this:
var Seq(a, b, c) = Seq.fill(3)(4)
As with Ivan's solution, this only works when declaring vars or vals, not when reassigning. Since the second parameter is computed for each element, it even works well for mutable objects:
import scala.collection.mutable.ListBuffer
var Seq(a, b, c) = Seq.fill(3)(ListBuffer[Int]())
a += 1 // Only modifies a, not b or c.
By contrast, something like a = b = c = [] will only create one list in most programming languages (e.g. Python, JavaScript, Java). If you don't want to create your object each time (perhaps because it is immutable and creation is expensive), declare it as val first to prevent this behavior:
val largeObject = ???
var Seq(a, b, c) = Seq.fill(3)(largeObject)
I'm trying to pass a default args in a function like we can do in method ..But im getting an error. Is it possible to pass a default args / named args to a function like method?
Is it possible to pass named arguments in function while calling it ?
This only works for methods (which are defined with def).
def func(i: Int = 2) = i
However, here is somewhat of a "hack" to do it regardless.
You can use a curried function here
def sum1(a:Int=2)(b:Int) = a+b
sum1(33)
Hope this answers your question.
var f(i:Int=2,j:Int) => i + j
This does not work. If you want to define a lambda, try this
val f = (i:Int,j:Int) => i + j
This is the correct approach. Also you cannot assign default values in lambda. You need to define methods with def keyword. Try this:
def f(i:Int, j:Int=2) = i + j
Parameter with default value should be the last parameter because scala compiler will scan values from left-right. It'll only use default values if there are missing ones. In above code f(1) will produce 3 because j will use 2 as default value. So use the compulsory arguments in the left side and the ones with default values on right. Hope this helps
Explained here: In Scala, can you make an anonymous function have a default argument?
Named arguments work with function definitions. Parameters with defaults don't need to be given:
class my
{
def f(i:Int = 2, j: Int) = i + j
}
var my = new my()
my.f(j = 1) // i = 2, j = 1
my.f(i = 3, j = 1) // i = 3, j = 1
my.f(3, 1) // i = 3, j = 1
class Cell(var x: Int)
var c = new Cell(1)
val f1 = () => c.x /* Create a closure that uses c */
def foo(e: Cell) = () => e.x /* foo is a closure generator with its own scope */
// f2 wont do any reference/deep copy
val f2 = foo(c) /* Create another closure that uses c */
val d = c /* Alias c as d */
c = new Cell(10) /* Let c point to a new object */
d.x = d.x + 1 /* Increase d.x (i.e., the former c.x) */
// now c.x refers to 10
println(f1()) /* Prints 10 */
println(f2()) /* Prints 2 */
Here the f2() prints 2 , As scala wont do deep copy, why the value is still persisted as 1, it should be 10.. where i am going wrong
2) I had read smomehere, Closure in scala dont deep copy the objects, they just keep reference to the object. what do it exactly mean
Your example is somewhat tough to understand due to the way you copied it in (it looks like all the code is run when a Cell is created, but you'd get infinite recursion if that were true). The reason f1 and f2 return different results is that they are pointing at different Cells. You are right that when you write:
val d = c
both c and d contain the same reference. But when you write:
c = new Cell(10)
c is now a reference to a new cell, and d won't copy over that reference.
It's easier to see this with REPL, which can print hexadecimal reference locations.
scala> class Cell(var x: Int)
defined class Cell
scala> var a = new Cell(5)
a: Cell = Cell#368239c8
scala> val b = a
b: Cell = Cell#368239c8
We can see that a and b contain references to the same cell.
scala> a.x = 10
a.x: Int = 10
scala> b.x
res0: Int = 10
When we update the class referenced by a, it also updates for b.
scala> a = new Cell(7)
a: Cell = Cell#5b87ed94
scala> b
res1: Cell = Cell#368239c8
scala> a.x
res2: Int = 7
scala> b.x
res3: Int = 10
When we assign our variable a to a new cell, it has a different reference location (it is a different instance of Cell). b still has the same reference (why wouldn't it?).
If a is identical to c, b is identical to c, why a is not identical to b?
var a = [1, 2, 3]
var b = a
var c = a[0...2]
a === c // true
b === c // true
a === b // false
If a, b, c are constants:
let a = [1, 2, 3]
let b = a
let c = a[0...2]
a === c // true
b === c // true
a === b // true
You can remove the import Cocoa or import UIKit if you are playing with PlayGround to make it correct. It seems there is some type map thing in the Cocoa framework to mess things up. It should be a bug, I think.
As #onevcat said, it's might be a bug of Playground. And if you change a to objects of reference type, all the identity tests will be true.
class K {}
var a = [K(), K(), K()]
var b = a
var c = a[0...2]
a === c // true
b === c // true
a === b // true
it means that a, b & c share the same storage and elements.
Interesting, my guess is that since c is a var in the first case, its mutable and thus it has to make a copy. That way if you add on to c it wouldn't modify a. In the second case, they are all immutable so they can point to the same memory space
Let´s say I have following object:
dict = { a: 1, b: 2, c: 3 }
following works perfectly:
{a, b} = dict
// -> a = 1
// -> b = 2
Now I want to manipulate those numbers and write it back to the object and clearly following line does not work:
// some manipulations
dict = {a, b}
Obviously I have overwritten the dict object. What I essentially wanted to do is assign dict.a = a and dict.b = b with dict.c staying as it is.
Is it possible to achieve my goal with some sort of a short notation?
You can extract a slice of an object into separate local variables using:
{a, b} = dict
but there's no way to assign to a slice of an object, i.e. you can't do things like this:
dict{a, b} = [ x, y ]
as a shortcut for
dict.a = x
dict.b = y
You can't even extract an object slice into a new object with things like this:
obj = dict{a, b}
you have to do it in two steps:
{ a, b } = dict
obj = { a, b }
Destructured assignments work well to pull things out of objects but they're not that useful for putting things back into objects. I think the closest you can get is to use a destructured array assignment:
[ dict.a, dict.b ] = [ a, b ]
If you're working with several keys, then you could put the keys in an array and do the slicing and merging with loops (possibly wrapped in helper functions):
slice = (obj, keys...) ->
s = { }
s[k] = obj[k] for k in keys
s
merge = (dest, src) ->
dest[k] = src[k] for k of src
return
keys = [ 'a', 'b' ]
dict = { a: 1, b: 2, c: 3 }
s = slice(dict, keys...)
s.a += 6
s.b += 6
merge(dict, s)
# dict is now { a: 7, b: 8, c: 3 }
Or just use the Underscore, jQuery, ... utility functions.
In pure coffeescript:
extend = (a, others...) ->
for o in others
a[key] = val for key, val of o
a
dict = { a: 1, b: 2, c: 3 }
{a, b} = dict
a = 5
b = 8
extend dict, {a, b}
console.log dict
#dict = { a: 5, b: 8, c: 3 }
Assuming you are using underscore.js, I would do this:
dict = { a: 1, b: 2, c: 3 }
{a, b} = dict
...
dict = _.extend dict, {a:a, b:b}
As asawyer points out, there's a similar extend function in jQuery too.