Is storing an object literal inside immutable a valid pattern...? - immutability

so I have Immutable.js in the form of:
let o = immutable.Map({a: {b: 1}})
and so my question is, would it be valid to do:
o.get('a').b = 2
which will return just the value set, but not a new reference... :/
or other patterns recommended to modidy the internal state of an object literal inside the Immutable map?
I would appreciate if someone can expand on the pattern (if one even exists) of mixing immuatble.js with object literals and recommendations...
tx as always,
Sean.

You are correct in your assumption that the inner object literal is mutable. You can test this as:
var o = immutable.Map({a: {b: 1}})
o.get('a').b = 2;
// b will now be mutated in o;
If you would like to create a fully immutable object use the fromJS method provided with Immutable, which will do a deep conversion, or set the value of a to also be a Map.
Edited to add: Regarding appropriate patterns, I recommend going fully immutable as it maintains the contract that any inner objects/array are also immutable.

Related

Why can you change the value of a local variable in Ruby in a function using another method but not with an assignment operator?

I'm trying to understand the concept of Ruby as a pass-by-reference-value language. Using an example I found on this site...
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name
we get the output "WILLIAM". So value and name are both pointing at the same object, which is initially holding a value of "William" and then .upcase changes it to "WILLIAM". I would understand this as pass-by-reference.
But then if I change .upcase to =:
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
The output becomes "William". Which is pass by value.
Why does an assignment operator make the difference in how a variable is treated in Ruby?
The key here is that you can never change a Ruby object's core self, once it has been created it will always be the same object until garbage collected and destroyed. It is only possible to alter properties of the object.
You can, however, change variables or object references such as instance variables, constants, attr_accessor properties among other things.
So in this case:
def uppercase2(value)
value = "WILLIAM"
end
This reassigns the value local variable. It does nothing to the original object.
If you want to replace that text you need to use methods on the object to effect it, if supported. In this case there is a method:
def uppercase2(value)
value.replace("WILLIAM")
end
These are generally termed in-place modifications as in the object itself is manipulated rather than swapped for another object.
I'm trying to understand the concept of Ruby as a pass-by-reference-value language.
Ruby is pass-by-value. Always. It is never pass-by-reference. The value that is being passed is an immutable unforgeable pointer, but that is very different from pass-by-reference.
C is pass-by-value. And C has pointers. That doesn't mean that if you pass a pointer in C, it magically becomes pass-by-reference. It is still pass-by-value.
C++ has pointers, and it supports both pass-by-value and pass-by-reference. In C++, you can pass pointers by value or by reference and you can pass non-pointers by value or by reference. The two concepts are completely orthogonal.
If we can agree that C is pass-by-value, and we can agree that C has pointers, and we can agree that when we pass a pointer in C, that is still pass-by-value, then we must also agree that Ruby is pass-by-value, because Ruby behaves like a hypothetical version of C, where the only allowed types are "pointer to something", the only way to access a value is dereferencing the pointer, and the only way to pass a value is taking the pointer.
That does not change parameter passing in C in any way, which means it is still pass-by-value, which means if we call that in C pass-by-value, it doesn't make sense to call it anything else in Ruby.
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name
we get the output "WILLIAM". So value and name are both pointing at the same object, which is initially holding a value of "William" and then .upcase changes it to "WILLIAM". I would understand this as pass-by-reference.
Again, this is not pass-by-reference. Pass-by-reference would mean that you can change the reference in the caller's scope, which Ruby does not allow you to do.
This is nothing but simple mutation. Ruby is not a purely functional language, it does allow you to mutate objects. And when you mutate an object, you can observe its changed state regardless of what name you call it.
My friends call me "Jörg" but my barber calls me "Mr. Mittag". When my barber cuts my hair, it doesn't magically grow back when I meet my friends, it will still be gone even though they don't refer to me by the same name as my barber does.
You have two names for the same object, and you mutate that object. You will observe the new state regardless of which name you use to refer to that object.
That is simply "mutable state", it has nothing to do with pass-by-reference.
But then if I change .upcase to =:
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
The output becomes "William". Which is pass by value.
Why does an assignment operator make the difference in how a variable is treated in Ruby?
It doesn't. Both cases are pass-by-value. In the second case, you created a new object and assigned it to the local variable value inside the uppercase2 method. (Technically, it is not a local variable, it is a parameter binding, but it can be rebound inside the method body, precisely because Ruby is pass-by-value. If it were pass-by-reference, then this would have also reassigned the name local variable to the newly created object.)
Sometimes, this specific case of pass-by-value, where the value being passed is an immutable pointer to a potentially mutable object is called call-by-object-sharing, call-by-sharing, or call-by-object. But that is not something different from pass-by-value. It is still pass-by-value. It is a special case of pass-by-value, where the value cannot be "any value" but is always "an immutable unforgeable pointer".
Sometimes, you will hear the description "Ruby is pass-by-value where the value that is being passed is a reference" or "Ruby is pass-by-reference-value" or "Ruby is pass-by-value-reference" or "Ruby is pass-by-object-reference". I don't really like these terms, because they sound very close to "pass-by-reference", but actually the term "reference" in "pass-by-reference" and the term "reference" in "pass-by-object-reference" mean two different things.
In "pass-by-reference", the term "reference" is a technical term that can be thought of as a generalization of the concept of "variable", "storage location", etc. Wheres in "pass-by-value-reference", we are talking about "object references", which are more like pointers but cannot be manufactured or changed.
I also don't like the terms that I used above "pass-by-value where the value being passed is an immutable unforgeable pointer", because the term "pointer" has certain connotations, especially for people coming from C. In C, you can do pointer arithmetic, and you can cast a number to a pointer, i.e. you can "conjure up a pointer out of thin air". You can do none of that in Ruby. That's why I add the adjectives "immutable" (no arithmetic) and "unforgeable" (you cannot create a pointer, only be handed one by the system), but people overlook or ignore them or underestimate their importance.
In some languages, these immutable unforgeable pointers to objects are called "object references" (which is again dangerous because it invites confusion with "pass-by-reference") or OOPS (Object-Oriented PointerS) which has the unfortunate connotations of the mostly unrestricted free-for-all "C" pointers. (Go, for example, has much more restrictive pointers, but when you simply say the word "pointer", nobody thinks of Go.)
Note that none of this is really specific to Ruby. Python, ECMAScript, Java, and many others behave the same way. C# behaves the same way by default, but also supports pass-by-reference as an explicit opt-in. (You must explicitly request pass-by-reference both at the method definition and at the method call.) Scala behaves the same way by default, but optionally supports call-by-name.
C# is actually a very good way of demonstrating the distinctions, because C# supports both pass-by-value and pass-by-reference, both value types and reference types, and obviously, you can write types both as mutable and immutable types, so you actually get all 8 possible different combinations and you can study how they behave.
I came up with this simple test code, which you can easily translate into other languages as well:
def is_ruby_pass_by_value?(foo)
foo.replace('More precisely, it is call-by-object-sharing!')
foo = 'No, Ruby is pass-by-reference.'
end
bar = 'Yes, of course, Ruby *is* pass-by-value!'
is_ruby_pass_by_value?(bar)
p bar
# 'More precisely, it is call-by-object-sharing!'
Here is the slightly more involved example in C#:
struct MutableCell { public string value; }
static void ArgumentPassing(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
ArgumentPassing(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
Let's start breaking this down in something more understandable.
You can compare a variable like name (or value) with a signpost.
Let's say I point it to the a beige house, which will be the value of the variable.
With the above in mind let's take a look at the first example:
# don't worry about this line for now
House = Struct.new(:color)
def color_red(value)
value.color = :red
end
house = House.new(:beige)
color_red(house)
puts house
# prints: #<struct House color=:red>
So what happens here? When we pass house as parameter to color_red Ruby will copy our signpost and assign it to value. Now both signposts point to the same house. We then follow the directions of signpost value and walk to the house and paint it red.
For this reason the color of house will end up being red.
Now let's have a look at the other example:
def color_red(value)
value = House.new(:red)
end
house = House.new(:beige)
color_red(house)
puts house
# prints: #<struct House color=:beige>
Here we start of the same, we copy our signpost house and assign the copy to value. However instead of walking up to the house and painting it, we are going to modify the signpost and point it to a red house somewhere further down the street. And because our signpost value is a copy of house, pointing it in a new direction will not effect house.
Your code is doing the same thing. When you call value.upcase! you are saying to she string. Hey you, upcase all your characters! (Similar to painting the house.)
When you reasign value (value = "WILLIAM") you are essentially just modifying the signpost and pointing it to a new direction. However the signpost is passed as a copy so it does not effect the original.
def uppercase(value)
value.upcase!
end
name = 'William'
uppercase(name)
puts name #WILLIAM
In this case, you are mutating the original object. name points to William
and so does value. When you pass in the argument, Ruby will assign
the parameter variable value to the same object that name is pointing to.
def uppercase2(value)
value = "WILLIAM"
end
name = 'William'
uppercase2(name)
puts name
In this case, you are reassigning value. That is, you are changing which
object value is pointing to. It was pointing to the same string object that
name was pointing to. But, now, you are asking value to reference a
different object.
So, in summary, upcase! mutates the object while = will re-assign.
You can think of 3 circles, value is in one, name in another and William
in the third.
value and name both point to the string object, William.
In the first situation, you mutate the string object that both value and name
are pointing to.
In the second situation, you are creating a 4th circle, which has WILLIAM in it. Then you are erasing the line from value to William and creating a line
from value to WILLIAM.
You get the idea if I do this:
def uppercase2(value)
value = "WILLIAM"
puts value
end
name = 'William'
uppercase2(name) # => “WILLIAM”
puts name # William

Why cant nullable arrays/hashmaps be accessed using []

When I have a nullable array/list/hashmap such as
var x: ArrayList<String>? = null
I know can access the element at index 1 like so
var element = x?.get(1)
or I could do it in a unsafe way like this
var element = x!![1]
but why can't I do something like this
var element = x?[1]
what's the difference between getting elements from an array using the first example and the last example, and why is the last example not allowed?
In the first example, you're using the safe call operator ?. to call the get function with it.
In the second example, you're using the [] operator on the non-nullable return value of the x!! expression, which of course is allowed.
However, the language simply doesn't have a ?[] operator, which would be the combination of the two. The other operators offered are also don't have null-safe variants: there's no ?+ or ?&& or anything like that. This is just a design decision by the language creators. (The full list of available operators is here).
If you want to use operators, you need to call them on non-nullable expressions - only functions get the convenience of the safe call operator.
You could also define your own operator as an extension of the nullable type:
operator fun <T> List<T>?.get(index: Int) = this?.get(index)
val x: ArrayList<String>? = null
val second = x[2] // null
This would get you a neater syntax, but it hides the underlying null handling, and might confuse people who don't expect this custom extension on collections.

Why doesn't Typescript Intellisense show Object extensions?

Consider this code to extend the Object type:
interface Object
{
doSomething() : void;
}
Object.prototype.doSomething = function ()
{
//do something
}
With this in place, the following both compile:
(this as Object).doSomething();
this.doSomething();
BUT: when I'm typing the first line, Intellisense knows about the doSomething method and shows it in the auto-completion list. When I'm typing the second line, it does not.
I'm puzzled about this, because doesn't every variable derive from Object, and therefore why doesn't Visual Studio show the extra method in the method list?
Update:
Even though the Intellisense doesn't offer the method, it does seem to recognize it when I've typed it manually:
What could explain that?!
...because doesn't every variable derive from Object
No, for two reasons:
1. JavaScript (and TypeScript) has both objects and primitives. this can hold any value (in strict mode), and consequently can be a primitive:
"use strict";
foo();
foo.call(42);
function foo() {
console.log(typeof this);
}
Here's that same code in the TypeScript playground. In both cases (here and there), the above outputs:
undefined
number
...neither of which is derived from Object.
2. Not all objects inherit from Object.prototype:
var obj = Object.create(null);
console.log(typeof obj.toString); // undefined
console.log("toString" in obj); // false
If an object's prototype chain is rooted in an object that doesn't have a prototype at all (like obj above), it won't have the features of Object.prototype.
From your comment below:
I thought even primitives like number inherit from Object. If number doesn't, how does number.ToString() work?
Primitives are primitives, which don't inherit from Object. But you're right that most of them seem to, because number, string, boolean, and symbol have object counterparts (Number, String, Boolean, and Symbol) which do derive from Object. But not all primitives do: undefined and null throw a TypeError if you try to treat them like objects. (Yes, null is a primitive even though typeof null is "object".)
For the four of them that have object counterparts, when you use a primitive like an object like this:
var a = 42;
console.log(a.toString());
...an appropriate type of object is created and initialized from the primitive via the abstract ToObject operation in the spec, and the resulting object's method is called; then unless that method returns that object reference (I don't think any built-in method does, but you can add one that does), the temporary object is immediately eligible for garbage collection. (Naturally, JavaScript engines optimize this process in common cases like toString and valueOf.)
You can tell the object is temporary by doing something like this:
var a = 42;
console.log(a); // 42
console.log(typeof a); // "number"
a.foo = "bar"; // temp object created and released
console.log(a.foo); // undefined, the object wasn't assigned back to `a`
var b = new Number(42);
console.log(b); // (See below)
console.log(typeof b); // "object"
b.foo = "bar"; // since `b` refers to an object, the property...
console.log(b.foo); // ... is retained: "bar"
(Re "see below": In the Stack Snippets console, you see {} there; in Chrome's real console, what you see depends on whether you have the console open: If you don't, opening it later will show you 42; if you do, you'll see ▶ Number {[[PrimitiveValue]]: 42} which you can expand with the ▶.)
Does number implement its own toString method, having nothing to do with Object?
Yes, but that doesn't really matter re your point about primitives and their odd relationship with Object.
So to round up:
this may contain a primitive, and while some primitives can be treated like objects, not all can.
this may contain an object reference for an object that doesn't derive from Object (which is to say, doesn't have Object.prototype in its prototype chain).
JavaScript is a hard language for IntelliSense. :-)

Immutable value of type '[String]' only has mutating members named 'sort'

Reading Apple's Swift guide, more specifically the Closures chapter I've stumbled upon a problem. A String array is declared
var names = ["Cris", "Alex", "Ewa", "Barry", "Daniella"]
The purpose of this section is to pass an array of Strings (the one above) and with the function sort(_:) have the same array back but sorted using an auxiliary method by providing a closure. The closure is the method backwards
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
Then an array, reversed, is declared and applied the method sort to the original array, names:
var reversed = names.sort(backwards)
AFAIK reversed should be inferred as an array of Strings but when I check it is inferred as var reversed: <>. Now, reversed doesn't store anything and an error pops up:
Immutable value of type '[String]' only has mutating members named 'sort'
Later on in the chapter the closure is simplified a lot but I get the same error as now so I tried to fix it when the expression is simple enough but I have no clue on what to do.
I don't know if the book forgot something or is my mistake, help will be appreciated. Thank you in advance!

BiConsumer cannot modify argument

I implemented a Collector for a java 8 stream that will store Entities to a Repository when a given threshold is hit.
public BiConsumer<Tuple2<Integer,List<T>>, T> accumulator() {
return (tuple, e) -> {
List<T> list = tuple._2;
list.add(e);
if (list.size() >= this.threshold) {
this.repository.save(list);
this.repository.flush();
list = new LinkedList<>();
}
tuple = new Tuple2<>(tuple._1 + 1, list);
};
}
This does not work as intended. The the Element e is added to the list but is not reset after the threshold is reached. Also Integer stays at 0 which is to be expected since its a final member.
As it seems my only option is to make my Tuple2 mutable and empty the List :-(
Any suggestions how to solve this using immutable tuples?
A lambda expression can be thought of as a function (or method) that simply doesn't have a name. In this example it would be like a method that has two formal parameters tuple and e and also some local variables within its body, including list.
When you make an assignment to a formal parameter or to a local variable, that assignment is local to the current method (or lambda body). No mutation or side effects will be visible to the outside after the accumulator returns, so these assignments won't affect the data structure you're collecting into.
I'm not entirely sure what you're trying to do, but instead of using a tuple (which presumably is immutable and must be replaced instead of mutated) you might try writing an ordinary, mutable class that contains an integer counter (or whatever) and a list. The accumulator would add to the list, conditionally flush and replace the list, and increment the counter. These mutative operations are allowed in collectors because the collector framework carefully thread-confines these operations, so the object you're mutating doesn't need to be thread-safe.

Resources