Dart - assign value only if null (??=) gives warning message - dart

When I execute this small dart program:
void main() {
int? someint;
someint ??= 123;
someint ??= 246;
print(someint);
}
I get the following warning message;
$ dart test.dart
test.dart:4:3: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
someint ??= 246;
^
123
So everything works as expected, but the warning message is annoying. Is there any way to suppress this warning message?

This is simply a warning because the compiler knows that it is impossible that the assignment will occur as you had just done a nullish assign before. There is a better error message on dart pad:
void main() {
int? someint;
someint ??= 123;
someint ??= 246; // <- warning here
print(someint);
}
line 4 • The left operand can't be null, so the right operand is never executed. (view docs)
Try removing the operator and the right operand.
Your code still compiles, although there is no reason why you should do another nullish assign as it would never run.

Related

Could someone explain how this works: const print = #import("std").debug.print;

How can this const print variable behave like a function?
const print = #import("std").debug.print;
print("hello, world", .{});
I understand you can assign expressions to variables. But this seems to behave like a precompiler macro in c/c++, I wouldn't have guessed that.
Is it because "all variables declared in a comptime expression are implicitly comptime variables" and # makes it a comptime expression, so it is evaluated before compilation, much like a macro would in c?
Could someone elaborate a bit? This seems a very powerful feature.
# does not indicate a comptime expression; rather # prefixes built-in functions in Zig. #import returns a struct that provides access to the declarations made public by the imported file.
The expression #import("std").debug.print evaluates to the print function defined in the standard library file std/debug.zig; it is not the expression that is assigned to print in the posted code, but the function. That is, the posted code works because print in OP code is actually a function. This can be seen by running the code below:
const print = #import("std").debug.print;
pub fn main() void {
print("#TypeOf print: {}\n", .{ #TypeOf(print) });
}
Results:
$ zig run print_type.zig
#TypeOf print: fn(comptime []const u8, anytype) void
Function Assignment
OP has asked for another example of assigning a function that is not imported to an identifier:
const print = #import("std").debug.print;
fn my_function(msg: []const u8) void {
print("{s}\n", .{ msg });
}
const my_function_alias = my_function;
pub fn main() void {
const another_function_alias = my_function;
const yet_another_function_alias = my_function_alias;
my_function("mf");
my_function_alias("mfa");
another_function_alias("afa");
yet_another_function_alias("yafa");
}
Program output:
$ zig run function_assignment.zig
mf
mfa
afa
yafa

const constructor initialisation failure in Dart

The following:
import 'package:flutter/foundation.dart';
class Bar {
final int tender;
const Bar(this.tender);
}
class Foo {
final int foo;
final Bar bar;
const Foo({#required foo})
: foo = foo,
bar = const Bar(foo);
}
results in the compiler error "Arguments of a constant creation must be constant expressions" for the attempted initialization bar = const Bar(foo). Why does that line fail, when the preceding line foo = foo does not?
EDIT Just to further clarify the source of confusion: effectively, it's as if it's ok to const-construct a Foo with the argument foo (which is unknown at compile-time), but it's not ok to const-construct a Bar with the exact same argument. Why?
The line fails because a variable is being passed instead of a constant/literal to create the const object of Bar. The compiler doesn't know what foo is going to be at compile time and hence it fails to create a const Bar(foo)
Consider this :
void main(){
int someNonConstantValue = 10;
const Bar(someNonConstantValue);
}
Compiler warns here with the same error message
Arguments of a constant creation must be constant expressions
This is because someNonConstantValue is not a constant.
Now if the code is modified as :
void main(){
const int someConstantValue = 10;
const Bar(someConstantValue);
}
There are no warnings because compiler is now assured that someConstantValue is actually constant and wont change anytime (and hence it can compile and optimize the code).
Similarly, In the original example, compiler doesn't give error if changes are made as such to use a constant literal for creating const Bar(
class Bar {
final int tender;
const Bar(this.tender);
}
class Foo {
final int foo;
final Bar bar;
const Foo({#required this.foo})
: bar = const Bar(10);
}
Addition :
Following the same explanation as above, error is given if const Foo( is passed a variable
void main(){
int someNonConstantValue = 10;
const Foo(foo:someNonConstantValue);
}
The point you are referring to is the constructor declaration inside its own class. It hasn't been invoked with any value yet.
EDIT:
This github issue is a discussion on similar lines from early days of Dart.
This answer provides explanation about the same.

Variadic Dispatch Function

I have an interface wherein the types of the parameters mostly encode their own meanings. I have a function that takes one of these parameters. I'm trying to make a function that takes a set of these parameters and performs the function on each one in order.
#include <iostream>
#include <vector>
enum param_type{typeA,typeB};
template <param_type PT> struct Container{
int value;
Container(int v):value(v){}
};
int f(Container<typeA> param){
std::cout<<"Got typeA with value "<<param.value<<std::endl;
return param.value;
}
int f(Container<typeB> param){
std::cout<<"Got typeB with value "<<param.value<<std::endl;
return param.value;
}
My current solution uses a recursive variadic template to delegate the work.
void g(){}
template <typename T,typename...R>
void g(T param,R...rest){
f(param);
g(rest...);
}
I would like to use a packed parameter expansion, but I can't seem to get that to work without also using the return values. (In my particular case the functions are void.)
template <typename...T> // TODO: Use concepts once they exist.
void h(T... params){
// f(params);...
// f(params)...; // Fail to compile.
// {f(params)...};
std::vector<int> v={f(params)...}; // Works
}
Example usage
int main(){
auto a=Container<typeA>(5);
auto b=Container<typeB>(10);
g(a,b);
h(a,b);
return 0;
}
Is there an elegant syntax for this expansion in C++?
In C++17: use a fold expression with the comma operator.
template <typename... Args>
void g(Args... args)
{
((void)f(args), ...);
}
Before C++17: comma with 0 and then expand into the braced initializer list of an int array. The extra 0 is there to ensure that a zero-sized array is not created.
template <typename... Args>
void g(Args... args)
{
int arr[] {0, ((void)f(args), 0)...};
(void)arr; // suppress unused variable warning
}
In both cases, the function call expression is cast to void to avoid accidentally invoking a user-defined operator,.

Streams backport compile error

Using streamsupport with a Java 7 javac compiler I encounter the following compile error:
[ERROR] method map in interface java8.util.stream.Stream<T>
cannot be applied to given types; [ERROR] required:
java8.util.function.Function<? super java.lang.Object,? extends
R>
[ERROR] found: <anonymous
java8.util.function.Function<java.lang.Integer,java.lang.String>> [ERROR] reason: no instance(s) of type variable(s) R exist so that
argument type <anonymous
java8.util.function.Function<java.lang.Integer,java.lang.String>> conforms to formal parameter type java8.util.function.Function<?
super java.lang.Object,? extends R>
My code is
List<Object> listSum = RefStreams.iterate(0, new UnaryOperator<Integer>() {
#Override
public Integer apply(Integer n) {
return n+1;
}
}).limit(10000).map(new Function<Integer,String>() {
#Override
public String apply(Integer n) {
return String.format("%04d", n);
}
}).collect(Collectors.toList());
I want to know what to do and why this error occurred? Thanks
You'll have to be prepared that type inference in Java 6 / 7 compilers is not up to par with Java 8 / Java 9 compilers.
So, sometimes a statement / expression that compiles with 8 can't be compiled unchanged with 6 or 7. Providing a type witness usually helps the compiler figure out the correct types in Java 6 / 7.
I would do it this way (this works for me with javac from Oracle JDK 1.7.0_80):
List<String> list = RefStreams.<Integer, Integer>iterate(0, new UnaryOperator<Integer>() {
#Override
public Integer apply(Integer n) {
return n + 1;
}
}).limit(10000).map(new Function<Integer, String>() {
#Override
public String apply(Integer n) {
return String.format("%04d", n);
}
}).collect(Collectors.<String>toList());
Note the two type witnesses here:
RefStreams.<Integer, Integer>iterate and Collectors.<String>toList.
The first is there to help the compiler infer the correct type for the map call and the second is there so that the result is correctly inferred as List<String> instead of List<Object>.

Is "Oops: ; return error;" a valid method declaration in C?

#include <stdio.h>
#include <AssertMacros.h>
int main( int argc, char* argv[] )
{
int error = 1;
verify_noerr( error );
require_noerr( error, Oops ); //<---- Is Oops a callback method?
printf("You shouldn't be here!\n");
Oops: ; // <--v____ Is this a method declaration?
return error; // <--^ Why the ':' followed by the ';'?
}
This code is from iOS documentation from 2006. I realize that in C the default return type for a method with no declared return type is int. But is this really a method that is leaning on that principle? And why the colon semicolon? My last thought was that its a C block, but Wikipedia says otherwise.
I'm stumped.
This:
Oops: ;
is a label, which can be the target of a goto.
I'm guessing that require_noerr is a macro that expands to a goto to the given label if error is an error code.
You'd use this system to exit from a function when an error occurred. It allows for cleanup code between the label and the end of the function (which a simple if (error) return; doesn't).
this is called a label in C programming.
in c code you can use goto to jump to this label
goto Oops;

Resources