CoffeeScript: assigning multiple properties to an initialised object - coffeescript

w = {c: true}
w =
a: 4
b: true
console.log w
I expect the result w to be {a: 4, b: true, c: true}, but I get {a: 4, b: true}.
How can I do multiple assignments to object properties without loosing already set properties?

CoffeeScript: assigning multiple properties to an initialised object has been the best answer so far.
But if you only want to add a few properties to an object you can just do:
w = {c: true}
w.a = 4
w['b'] = true # alternative notation
Also, this question is more about JavaScript than CoffeeScript.

I don't think it can be done directly. I believe, you need to iterate:
w = {c: true}
temp =
a: 4
b: true
w[k] = v for k,v of temp
console.log w

w = {c: true}
w[i] = v for i,v of {
a: 4
b: true
}
console.log w

Related

Assign same value to multiple variables in Scala

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)

An algorithm that determines if a function f from the finite set A to the finite set B is an onto function.

How can I write an algorithm that determines if a function f from the finite set A to the finite set B is an onto function.
This is what I have so far:
A: array ( members of set A )
B: array ( members of set B )
Mapped: associative array of Boolean variables.
for each b in B:
Mapped[b] = false
for each a in A:
Mapped[f(a)] = true
Onto = true;
for each b in B:
Onto = Onto AND Mapped[b]
return Onto
Is this correct?
Yeah, that'll work. A potentially easier approach would be
for each a in A:
remove f(a) from B
return (is B empty?)
And then of course you should sort B first, so you can remove more quickly.

Nim operator overloading

Just started programming in the Nim language (which I really like so far). As a learning exercise I am writing a small matrix library. I have a bunch more code, but I'll just show the part that's relevant to this question.
type
Matrix*[T; nrows, ncols: static[int]] = array[0 .. (nrows * ncols - 1), T]
# Get the index in the flattened array corresponding
# to row r and column c in the matrix
proc index(mat: Matrix, r, c: int): int =
result = r * mat.ncols + c
# Return the element at r, c
proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]
# Set the element at r, c
proc `[]=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] = val
# Add a value to every element in the matrix
proc `+=`(mat: var Matrix, val: Matrix.T) =
for i in 0 .. mat.high:
mat[i] += val
# Add a value to element at r, c
proc `[]+=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] += val
# A test case
var mat: Matrix[float, 3, 4] # matrix with 3 rows and 4 columns
mat[1, 3] = 7.0
mat += 1.0
# add 8.0 to entry 1, 3 in matrix
`[]+=`(mat, 1, 3, 8.0) # works fine
All this works fine, but I'd like to be able to replace the last line with something like
mat[1, 3] += 4.0
This won't work (wasn't expecting it to either). If I try it, I get
Error: for a 'var' type a variable needs to be passed
How would I create an addition assignment operator that has this behavior? I'm guessing I need something other than a proc to accomplish this.
There are two ways you can do this:
Overload [] for var Matrix and return a var T (This requires the current devel branch of Nim):
proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]
proc `[]`(mat: var Matrix, r, c: int): var Matrix.T =
result = mat[mat.index(r, c)]
Make [] a template instead:
template `[]`(mat: Matrix, r, c: int): expr =
mat[mat.index(r, c)]
This causes a problem when mat is not a value, but something more complex:
proc x: Matrix[float, 2, 2] =
echo "x()"
var y = x()[1, 0]
This prints x() twice.

Identity operators in Swift

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

CoffeeScript: Assigning values to object

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.