Swap the values of two variables using the tuple unpacking style - dart

In Python, you can swap the values of two variables using the following syntax
a, b = b, a
How to do this in Dart?

Python style tuple unpacking is not supported in Dart. Neither is the assignment of multiple variables as you have in your example. If it is the swap you are after, you could always just do the following:
var a = 10, b = 5, temp;
temp = a;
a = b;
b = temp;

As Shailen Tuli has mentioned, Python-style tuple unpacking is not supported in Dart. You can use Immediately invoked closures.
(tmp) {
a = b;
b = tmp;
}(a)
Which will do the trick.
Thanks to Mr. Randal Schwartz

I tried this:
swapper(int a,int b)
{
return {
"data":
{
'b' : b,
'a' : a
}
}['data'];
}

Related

Generic type inference in function from lists

I'm working on some generic list utility functions and there seems to be an issue with the type inference for a generic function when the primary variables are lists. This is demonstrated with the following code:
List<T> combine<T>(List<T> a, List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < a.length && i < b.length; i++) {
list.add(combiner(a[i], b[i]));
}
return list;
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = combine(a, b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}
When I use this code as-is, the type inference within the lambda sets a and b to be Object?, which results in the following error message:
The operator '+' can't be unconditionally invoked because the receiver can be 'null'.
Try adding a null check to the target ('!').
Doing what the error message says changes the message to the following:
The operator '+' isn't defined for the type 'Object'.
Try defining the operator '+'.
The issue obviously is that type inference is assigning the parameters to Object? instead of the expected int. This can be worked around by either typing the parameters or explicitly passing the generic type to the function:
final c = combine(a, b, (int a, int b) => a + b);
// OR
final c = combine<int>(a, b, (a, b) => a + b);
However, that's an added level of verbosity that I don't want to have to force the users of these utility functions to have to do (not to mention it will be a support issue when I have to explain to them to do this). Is there a way to change the function signature to make it so type inference works as expected?
This is basically Dart List.fold vs List.reduce type inference, but in your case you could sidestep the problem by making your function an extension method so that T is deduced from the receiver instead of from the arguments:
extension<T> on List<T> {
List<T> combineWith(List<T> b, T Function(T a, T b) combiner) {
final list = <T>[];
for (int i = 0; i < length && i < b.length; i++) {
list.add(combiner(this[i], b[i]));
}
return list;
}
}
void main() {
final a = [5, 8];
final b = [7, -3];
final c = a.combineWith(b, (a, b) => a + b); // Error
print(c);
// Expected: [12, 5]
}

Why is `functionArgs` implemented twice? (i.e, as a primop and in `lib`)

Trying to understand callPackage, so looked up its implementation where it uses lib.functionArgs (source), but there is already a builtins.functionArgs primop, an alias of __functionArgs (implemented in C).
lib.functionArgs is defined as
/* Extract the expected function arguments from a function.
This works both with nix-native { a, b ? foo, ... }: style
functions and functions with args set with 'setFunctionArgs'. It
has the same return type and semantics as builtins.functionArgs.
setFunctionArgs : (a → b) → Map String Bool.
*/
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
and the __functionArgs attribute above is coming from setFunctionArgs (source):
/* Add metadata about expected function arguments to a function.
The metadata should match the format given by
builtins.functionArgs, i.e. a set from expected argument to a bool
representing whether that argument has a default or not.
setFunctionArgs : (a → b) → Map String Bool → (a → b)
This function is necessary because you can't dynamically create a
function of the { a, b ? foo, ... }: format, but some facilities
like callPackage expect to be able to query expected arguments.
*/
setFunctionArgs = f: args:
{
__functor = self: f;
__functionArgs = args;
};
I understand what setFunctionArgs does, and the comment above its declaration tells why it is necessary, but I can't understand it; both clauses of that sentence are clear but not sure how the first statement prevents the second one to be achieved (without setFunctionArgs, that is).
danbst also tried to elucidate this further,
lib.nix adds __functionArgs attr to mimic __functionArgs builtin. It
used to "pass" actual __functionArgs result down to consumers, because
builtin __functionArgs only works on top-most function args
but not sure what the "consumers" are, and couldn't unpack the last clause (i.e., "builtin __functionArgs only works on top-most function args"). Is this a reference to the fact that Nix functions are curried, and
nix-repl> g = a: { b, c }: "lofa"
nix-repl> builtins.functionArgs g
{ }
?
lib.functionArgs also doesn't solve this problem, but I'm probably off the tracks at this point.
Notes to self
__functor is documented in the Nix manual under Sets.
$ nix repl '<nixpkgs>'
Welcome to Nix version 2.3.6. Type :? for help.
Loading '<nixpkgs>'...
Added 11530 variables.
nix-repl> f = { a ? 7, b }: a + b
nix-repl> set_f = lib.setFunctionArgs f { b = 9; }
nix-repl> set_f
{ __functionArgs = { ... }; __functor = «lambda # /nix/store/16blhmppp9k6apz41gjlgr0arp88awyb-nixos-20.03.3258.86fa45b0ff1/nixos/lib/trivial.nix:318:19»; }
nix-repl> set_f.__functionArgs
{ b = 9; }
nix-repl> set_f set_f.__functionArgs
16
nix-repl> set_f { a = 27; b = 9; }
36
lib.functionArgs wraps builtins.functionArgs in order to provide reflective access to generic functions.
This supports reflection with builtins.functionArgs:
f = { a, b, c }: #...
Now consider the eta abstraction of the same function:
f' = attrs: f attrs
This does not support reflection with builtins.functionArgs. With setFunctionArgs, you can restore that information, as long as you also use lib.functionArgs.
I recommend to avoid reflection because everything that I've seen implemented with it can be implemented without it. It expands the definition of a function to include what should normally be considered implementation details.
Anyway, the primary motivation seems to be callPackage, which can be implemented with normal attrset operations if you change all packages to add ... as in { lib, stdenv, ... }:. I do have a morbid interest in this misfeature that is function reflection, so if anyone finds another use case, please comment.

How does Nix's "callPackage" call functions defined without an ellipsis?

To call a Nix function that uses set destructuring, you need to pass it a set with exactly the keys it requires, no more and no less:
nix-repl> ({ a }: a) { a = 4; b = 5; }
error: anonymous function at (string):1:2 called with unexpected argument ‘b’, at (string):1:1
The exception to this is if the function's argument list contains an ellipsis at the end:
nix-repl> ({ a, ... }: a) { a = 4; b = 5; }
4
However, most of the packages in nixpkgs consist of a default.nix file containing a function which is not defined with this ellipsis. Yet, somehow when you use callPackage, it manages to call these functions and pass them only the arguments that they need. How is this implemented?
There is a reflection primop, that can deconstruct function argument:
nix-repl> __functionArgs ( { x ? 1, y }: x )
{ x = true; y = false; }
callPackage then iterates over those attribute names, fetches required packages and constucts the attrset of packages, that is fed later to called function.
Here's a simple example:
nix-repl> callWithExtraArgs = f: args:
let
args' = __intersectAttrs (__functionArgs f) args;
in
f args'
nix-repl> callWithExtraArgs ({ x }: x + 1) { x = 4; y = 7; }
5
To browse Nix primops, go to 15.5. Built-in Functions in the Nix manual (or see the docs of the unstable branch).

Names bound to both the decomposed discriminated union components AND an original composed value

I can't find documentation on this. I need to decompose a Discriminated Union value into some of its components but I also need to use the item as a whole within the body of a function as well.
I can do let matcher = function MyDU(_,b,_) -> b or let extractor MyDU(_,b,_) = b but what if I also need the reference to the MyDU value for something like ... -> RedundantWrapper(myDU, b)
I've tried:
let extractor myDU =
let MyDU(_,b,_) = myDU
RedundantWrapper(myDU, b)
but I don't think that is the right syntax. Perhaps I can do this some longer way, but it seems like there would be a short way.
Thanks!
Like this:
let (Some(x) as o) = Some 1
// val o : int option = Some 1
// val x : int = 1
Also, I just realized that this short-hand is allowed which I think everyone here will agree is PRETTY AWESOME.
let extractor (myDU & MyDU(_,b,_)) =
RedundantWrapper(myDU, b)

Need advice on the Swift while statement

The following code got compilation error:
var a : Int = 0
var b : Int = 3
var sum : Int = 0
while (sum = a+b) < 2 {
}
The error message is:
Cannot invoke '<' with an argument list of type '((()),
IntegerLiteralConvertible)'
How to solve this problem? (Of course I can put sum assignment statement out side the while statement. But this is not convenient. Any other advice? Thanks
In many other languages, including C and Objective-C, sum = a+b would return the value of sum, so it could be compared.
In Swift, this doesn't work. This was done intentionally to avoid a common programmer error. From The Swift Programming Language:
Swift supports most standard C operators and improves several capabilities to eliminate common coding errors. The assignment operator (=) does not return a value, to prevent it from being mistakenly used when the equal to operator (==) is intended.
Since the assignment operator does not return a value, it can't be compared with another value.
It is not possible to overload the default assignment operator (=), but you could create a new operator or overload one of the compound operators to add this functionality. However, this would be unintuitive to future readers of your code, so you may want to simply move the assignment to a separate line.
In most languages, assignments propagate their value -- that is, when you call
sum = a + b
the new value of sum is available for another part of the expression:
doubleSum = (sum = a + b) * 2
Swift doesn't work that way -- the value of sum isn't available after the assignment, so it can't be compared in your while statement. From Apple's documentation:
This feature prevents the assignment operator (=) from being used by
accident when the equal to operator (==) is actually intended. By
making if x = y invalid, Swift helps you to avoid these kinds of
errors in your code.
The other answers explain why your code won't compile. Here is how you can clean it up without calculating sum in the while loop (I'm assuming you want to be able to reassign what sum's getter is, elsewhere.):
var a = 0, b = 3
var getSum = { a + b }
var sum: Int { return getSum() }
while sum < 2 {
...and if you're okay with invoking sum with parentheses:
var a = 0, b = 3
var sum = { a + b }
while sum() < 2 {
You can rewrite it as a for loop, although you'll have to repeat the assignment and addition:
for sum = a+b; sum < 2; sum = a+b {
}

Resources