"exponentially large number of cases" errors in latest Flow with common spread pattern - flowtype

I frequently use the following pattern to create objects with null/undefined properties omitted:
const whatever = {
something: true,
...(a ? { a } : null),
...(b ? { b } : null),
};
As of flow release v0.112, this leads to the error message:
Computing object literal [1] may lead to an exponentially large number of cases to reason about because conditional [2] and conditional [3] are both unions. Please use at most one union type per spread to simplify reasoning about the spread result. You may be able to get rid of a union by specifying a more general type that captures all of the branches of the union.
It sounds to me like this isn't really a type error, just that Flow is trying to avoid some heavier computation. This has led to dozens of flow errors in my project that I need to address somehow. Is there some elegant way to provide better type information for these? I'd prefer not to modify the logic of the code, I believe that it works the way that I need it to (unless someone has a more elegant solution here as well). Asking here before I resort to // $FlowFixMe for all of these.
Complete example on Try Flow

It's not as elegant to write, and I think Flow should handle the case that you've shown, but if you still want Flow to type check it you could try rewriting it like this:
/* #flow */
type A = {
cat: number,
};
type B = {
dog: string,
}
type Built = {
something: boolean,
a?: A,
b?: B,
};
function buildObj(a?: ?A, b?: ?B): Built {
const ret: Built = {
something: true
};
if(a) ret.a = a
if(b) ret.b = b
return ret;
}
Try Flow

Related

In functional programming, is "saving the state" of an algorithm at the recursive function argument cheating?

for instance, lets suppose we had to write an algorithm to get the max value of an array of integers, could we still call the code functional if we make the recursive function return various information that simulates an assignment to a global object? an exemple:
function getMax(array, props={}) {
const {index = 0, actualMax = array[0]}= props ///initial props
const arrayNotEnded = array[index + 1] !== undefined
if (arrayNotEnded) {
const maxOf= (a, b) => a > b ? a : b
const newMax = maxOf(actualMax, array[index+1])
const nextIndex = index+1
return getMax(array, {index:nextIndex, actualMax:newMax} )
}else return actualMax
}
a funny thing about that is, in Haskell, we cannot have optional arguments, so this logic would not be something cool to work with, since we would have to pass the initial props every time we would need to call this function.
Yes, you could consider it cheating, but this is a well-known technique in functional programming, the accumulator argument [1][2][3]. Remember: code doesn't become functional by not having state, functional programming is all about making state explicit. There's no better way of doing that than by making it a parameter of your function.
Your code has some other problems, though. Most prominently, the state should be internal to your function, only being passed to a helper function (that might be locally declared or separate) but not as part of your function's public interface. This also prevents confusing your helper function by passing invalid state (e.g. out-of-bound indices). And yes, also the optional parameter smells - not because you think this is not possible in Haskell (it is, using Maybe), but because it can be forgotten or passed mistakenly. Instead, the helper function should have a required state parameter, and getMax should have none.
Last but not least, you should avoid out-of-bounds indexed access on arrays - check the length to know where the end is, don't compare to undefined. This includes unconditionally accessing array[0] - that makes it very easy to overlook that your function can return undefined. Make this error condition explicit as well.
Here's how I'd write it:
function getMax(array) {
if (!array.length)
throw new Error("array must be non-empty");
else
return maxFrom(1, array[0]);
function maxFrom(index, max) {
if (index < array.length)
return maxFrom(index+1, array[index] > max ? array[index] : max);
else
return actualMax
}
}
Even better than throwing exceptions would be if you'd had an algebraic data type at hand that you could return to represent the error-or-result.

Kotlin - very frequent data removal and addition to a list causes npe

I've a buffer that is actually ArrayList<Object>.
Happens async:
This buffer list changes very frequently - I mean 15-50 times in single second and the idea is that whenever there's an update, I remove first element by position buffer.removeAt(0) and add new value in the end by buffer.add(new).
At some point I call a function that goes and do calculation with buffer list. What I do is I go through the list - element by element. At some point I run into NPE as the the element has been removed async.
How to solve this NPE? I was thinking of making deep copy, but making deep copy would mean to go through the buffer list and do some data allocation, which basically means that while I do deep copy I can still run into NPE.
How problems like these are solved?
How to solve NPE?
What would be more optimized way as this is gonna consume a lot of memory?
Code:
private fun observeFrequentData() {
frequentData.observe(owner, Observer { data ->
if (accelerationData == null) return#Observer
GlobalScope.launch {
val a = data[0].toDouble()
val b = data[1].toDouble()
val c = a + b
val timestamp = System.currentTimeMillis()
val customObj = CustomObj(c, timestamp)
if (buffer.size >= 5000) {
buffer.removeAt(0)
}
buffer.add(acceleration)
}
})
}
fun getBuffer() {
val mappedData = buffer.map { it.smth } // NPE, it == null
}
If you are doing lots of removing from 0, and insert at the end. Then ArrayList is probably not the container to use.
you can consider using a LinkedList .
buffer.removeFirst();
and
buffer.add(acceleration);
also note the following comments regarding synchronization.
Note that this implementation is not synchronized. If multiple threads
access a linked list concurrently, and at least one of the threads
modifies the list structurally, it must be synchronized externally. (A
structural modification is any operation that adds or deletes one or
more elements; merely setting the value of an element is not a
structural modification.) This is typically accomplished by
synchronizing on some object that naturally encapsulates the list. If
no such object exists, the list should be "wrapped" using the
Collections.synchronizedList method. This is best done at creation
time, to prevent accidental unsynchronized access to the list:
List list = Collections.synchronizedList(new LinkedList(...));
Using the synchronized keyword on your piece of code as #patrickf suggested.
To take care of performance, instead of making the method call itself synchronized, you can just write the 3 "buffer" related lines of code (size, removeAt and add) in a synchronized block.
Something like;
.
.
.
synchronized {
if (buffer.size >= 5000) {
buffer.removeAt(0)
}
buffer.add(acceleration)
}
}
})
Hope this helps!

Can a pure function change input arguments?

Is a function that changes the values of an input argument still a pure function?
My example (Kotlin):
data class Klicker(
var id: Long = 0,
var value: Int = 0
)
fun Klicker.increment() = this.value++
fun Klicker.decrement() = this.value--
fun Klicker.reset() {
this.value = 0
}
Wikipedia says a pure function has these two requirements:
The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.
From my understanding, all functions from my example comply with the first requirement.
My uncertainty starts with the second requirement. With the change of the input argument, I mutate an object (rule violation), but this object is not outside of the function scope, so maybe no rule violation?
Also, does a pure function always need to return a completely new value?
I presume, this function is considert 100% pure:
fun pureIncrement(klicker: Klicker): Klicker {
return klicker.copy(value = klicker.value++)
}
Be gentle, this is my first Stackoverflow question.
The increment and decrement functions fulfill neither of the requirements for a pure function. Their return value depends on the state of the Klicker class, which may change while program execution proceeds, so the first requirement is not fulfilled. The evaluation of the result mutates the mutable Klicker instance, so the second requirement is also not fulfilled. It doesn't matter in which scope the mutable data is; a pure function must not mutate any data at all.
The reset function violates only the second requirement.
The pureIncrement function can be made pure if you change it to:
fun pureIncrement(klicker: Klicker): Klicker {
return klicker.copy(value = klicker.value + 1)
}

Mutating a travelling window in a Rust ndarray

I am attempting to implement one iteration of Conway's Game of Life in Rust using the ndarray library.
I thought a 3x3 window looping over the array would be a simple way to count the living neighbours, however I am having trouble doing the actual update.
The array signifies life with # and the absence of life with :
let mut world = Array2::<String>::from_elem((10, 10), " ".to_string());
for mut window in world.windows((3, 3)) {
let count_all = window.fold(0, |count, cell| if cell == "#" { count + 1 } else { count });
let count_neighbours = count_all - if window[(1, 1)] == "#" { 1 } else { 0 };
match count_neighbours {
0 | 1 => window[(1, 1)] = " ".to_string(), // Under-population
2 => {}, // Live if alive
3 => window[(1, 1)] = "#".to_string(), // Re-produce
_ => window[(1, 1)] = " ".to_string(), // Over-population
}
}
This code does not compile! The error is within the match block with "error: cannot borrow as mutable" and "error: cannot assign to immutable index". I attempted for &mut window... but the library does not implement this(?)
I'm relatively new to Rust and I believe this may be an issue with the implementation of windows by the library. However, I'm not sure and I don't know if there perhaps some variation/fix that allows me to continue with this approach. Do I need to scrap this approach entirely? I'm not sure what the best approach would be here.
Any other suggestions or improvements to the code would be greatly appreciated.
(This code doesn't implement proper rules as I am mutating as I loop and I am ignoring the outer edge, however that is okay in this case. Also, any variations which do these things are also okay - the details are not important.)
Your general approach using ndarray and windows is ok, but the problem is that the values that you get from the windows iterator will always be immutable. You can work around that by wrapping the values in Cell or RefCell, which gives you interior mutability. That is, they wrap a value as if it was immutable, but provide an API to let you mutate it anyway.
Here is your code, fairly brutally adapted to use RefCell:
use ndarray::Array2;
use std::cell::RefCell;
fn main() {
// creating variables for convenience, so they can be &-referenced
let alive = String::from("#");
let dead = String::from(" ");
let world = Array2::<String>::from_elem((10, 10), " ".to_string());
let world = world.map(RefCell::new);
for mut window in world.windows((3, 3)) {
let count_all = window.fold(0, |count, cell| if *cell.borrow() == &alive { count + 1 } else { count });
let count_neighbours = count_all - if *window[(1, 1)].borrow() == &alive { 1 } else { 0 };
match count_neighbours {
0 | 1 => *window[(1, 1)].borrow_mut() = &dead, // Under-population
2 => {}, // Live if alive
3 => *window[(1, 1)].borrow_mut() = &alive, // Re-produce
_ => *window[(1, 1)].borrow_mut() = &alive, // Over-population
}
}
}
What I've done above is really just to get your code working, pretty much as-is. But, as E_net4 pointed out, your solution has a major bug because it is mutating as it reads. Also, in terms of best-practices, your usage of String isn't ideal. An enum is much better because it's smaller, can be stack-allocated and better captures the invariants of your model. With an enum you would derive Copy as below, which would let you use a Cell instead of RefCell, which is likely to be better performance because it copies the data, instead of having to count references.
#[derive(Debug, PartialEq, Clone, Copy)]
enum CellState {
Alive,
Dead
}

Weird behaviour with struct constructors

I've written a basic Node struct in D, designed to be used as a part of a tree-like structure. The code is as follows:
import std.algorithm: min;
alias Number = size_t;
struct Node {
private {
Node* left, right, parent;
Number val;
}
this(Number n) {val = n;}
this(ref Node u, ref Node v) {
this.left = &u;
this.right = &v;
val = min(u.val, v.val);
u.parent = &this;
v.parent = &this;
}
}
Now, I wrote a simple function which is supposed to give me a Node (meaning a whole tree) with the argument array providing the leaves, as follows.
alias Number = size_t;
Node make_tree (Number[] nums) {
if (nums.length == 1) {
return Node(nums[0]);
} else {
Number half = nums.length/2;
return Node(make_tree(nums[0..half]), make_tree(nums[half..$]));
}
}
Now, when I try to run it through dmd, I get the following error message:
Error: constructor Node.this (ulong n) is not callable using argument types (Node, Node)
This makes no sense to me - why is it trying to call a one-argument constructor when given two arguments?
The problem has nothing to do with constructors. It has to do with passing by ref. The constructor that you're trying to use
this(ref Node u, ref Node v) {...}
accepts its arguments by ref. That means that they must be lvalues (i.e. something that can be on the left-hand side of an assignment). But you're passing it the result of a function call which does not return by ref (so, it's returning a temporary, which is an rvalue - something that can go on the right-hand side of an assignment but not the left). So, what you're trying to do is illegal. Now, the error message isn't great, since it's giving an error with regards to the first constructor rather than the second, but regardless, you don't have a constructor which matches what you're trying to do. At the moment, I can think of 3 options:
Get rid of the ref on the constructor's parameters. If you're only going to be passing it the result of a function call like you're doing now, having it accept ref doesn't help you anyway. The returned value will be moved into the function's parameter, so no copy will take place, and ref isn't buying you anything. Certainly, assigning the return values to local variables so that you can pass them to the constructor as it's currently written would lose you something, since then you'd be making unnecessary copies.
Overload the constructor so that it accepts either ref or non-ref. e.g.
void foo(ref Bar b) { ... }
void foo(Bar b) { foo(b); } //this calls the other foo
In general, this works reasonably well when you have one parameter, but it would be a bit annoying here, because you end up with an exponential explosion of function signatures as you add parameters. So, for your constructor, you'd end up with
this(ref Node u, ref Node v) {...}
this(ref Node u, Node v) { this(u, v); }
this(Node u, ref Node v) { this(u, v); }
this(Node u, Node v) { this(u, v); }
And if you added a 3rd parameter, you'd end up with eight overloads. So, it really doesn't scale beyond a single parameter.
Templatize the constructor and use auto ref. This essentially does what #2 does, but you only have to write the function once:
this()(auto ref Node u, auto ref Node v) {...}
This will then generate a copy of the function to match the arguments given (up to 4 different versions of it with the full function body in each rather than 3 of them just forwarding to the 4th one), but you only had to write it once. And in this particular case, it's probably reasonable to templatize the function, since you're dealing with a struct. If Node were a class though, it might not make sense, since templated functions can't be virtual.
So, if you really want to be able to pass by ref, then in this particular case, you should probably go with #3 and templatize the constructor and use auto ref. However, personally, I wouldn't bother. I'd just go with #1. Your usage pattern here wouldn't get anything from auto ref, since you're always passing it two rvalues, and your Node struct isn't exactly huge anyway, so while you obviously wouldn't want to copy it if you don't need to, copying an lvalue to pass it to the constructor probably wouldn't matter much unless you were doing it a lot. But again, you're only going to end up with a copy if you pass it an lvalue, since an rvalue can be moved rather than copied, and you're only passing it rvalues right now (at least with the code shown here). So, unless you're doing something different with that constructor which would involve passing it lvalues, there's no point in worrying about lvalues - or about the Nodes being copied when they're returned from a function and passed into the constructor (since that's a move, not a copy). As such, just removing the refs would be the best choice.

Resources