In Vala I see that when I declare an array I have to specify the type, like
int[] myarray = { 1, 2, 3 };
I wonder if there is a way to have a mixed array like
smtg[] myarray = { 1, 'two', 3 };
I see that in this question they say that in C++ and C# it's not possible but I just started learning vala and I have no background with any C-like language so I want to be sure.
No.
That said, you can create an array of something that can hold other types, like GLib.Value or GLib.Variant, and Vala can automatically convert to/from those two, so you could do something like
GLib.Value[] values = {
1,
"two",
3.0
}
It's usually a terrible idea (you're basically throwing away compile time type safety), but you can do it.
Related
Which should I use in Dart? And why?
I understand that when omit_local_variable_types is used, it will naturally be the second use. If there is any other reason, please let me know.
List<int> numbers = [1,2,3];
var numbers = <int>[1,2,3];
Both declarations do the same thing here; it's simply a matter of preference.
It's worth noting that the Effective Dart guidelines recommend the use of the omit_local_variable_types lint.
Additionally, the following also works:
var numbers = [1, 2, 3];
Technically, the type of the list object is determined by the type specified on the right hand side if one is given (preventing type inference from the variable type being used). The following code would fail at runtime, because the created list is a List<int>.
List<num> numbers = <int>[1, 2, 3];
numbers[4] = 4.0;
Both the collection-for-in operation and .map() method can return some manipulation of elements from a previous collection. Is there ever any reason to prefer using one over the other?
var myList = [1,2,3];
var alteredList1 = [for(int i in myList) i + 2]; //[3,4,5]
var alteredList2 = myList.map((e) => e + 2).toList(); //[3,4,5]
Use whichever is easier and more readable.
That's a deliberately vague answer, because it depends on what you are doing.
Any time you have something ending in .toList() I'd at least consider making it into a list literal. If the body of the map or where is simple, you can usually rewrite it directly to a list literal using for/in (plus if for where).
And then, sometimes it gets complicated, you need to use the same variable twice, or the map computation uses a while loop, or something else doesn't just fit into the list literal syntax.
Then you can either keep the helper function and do [for (var e in something) helperFunction(e)] or just do something.map((e) { body of helper function }).toList(). In many cases the latter is then more readable.
So, consider using a list literal if your iterable code ends in toList, but if the literal gets too convoluted, don't feel bad about using the .map(...).toList() approach.
Readability is all that really matters.
Not an expert but personally I prefer the first method. Some reasons:
You can include other elements (independent from the for loop) in the same list:
var a = [1, 2, 3];
bool include5 = true;
var b = [
1,
for (var i in a) i + 1,
if (include5) 5,
];
print(b); // [1, 2, 3, 4, 5]
Sometimes when mapping models to a list of Widgets the .map().toList() method will produce a List<dynamic>, implicit casting won't work. When you come across such an error just avoid the second method.
I was trying to implement vector algebra with generic algorithms and ended up playing with iterators. I have found two examples of not obvious and unexpected behaviour:
if I have pointer p to a struct (instance) with field fi, I can access the field as simply as p.fi (rather than p.*.fi)
if I have a "member" function fun(this: *Self) (where Self = #This()) and an instance s of the struct, I can call the function as simply as s.fun() (rather than (&s).fun())
My questions are:
is it documented (or in any way mentioned) somewhere? I've looked through both language reference and guide from ziglearn.org and didn't find anything
what is it that we observe in these examples? syntactic sugar for two particular cases or are there more general rules from which such behavior can be deduced?
are there more examples of weird pointers' behaviour?
For 1 and 2, you are correct. In Zig the dot works for both struct values and struct pointers transparently. Similarly, namespaced functions also do the right thing when invoked.
The only other similar behavior that I can think of is [] syntax used on arrays. You can use both directly on an array value and an array pointer interchangeably. This is somewhat equivalent to how the dot operates on structs.
const std = #import("std");
pub fn main() !void {
const arr = [_]u8{1,2,3};
const foo = &arr;
std.debug.print("{}", .{arr[2]});
std.debug.print("{}", .{foo[2]});
}
AFAIK these are the only three instances of this behavior. In all other cases if something asks for a pointer you have to explicitly provide it. Even when you pass an array to a function that accepts a slice, you will have to take the array's pointer explicitly.
The authoritative source of information is the language reference but checking it quickly, it doesn't seem to have a dedicated paragraph. Maybe there's some example that I missed though.
https://ziglang.org/documentation/0.8.0/
I first learned this syntax by going through the ziglings course, which is linked to on ziglang.org.
in exercise 43 (https://github.com/ratfactor/ziglings/blob/main/exercises/043_pointers5.zig)
// Note that you don't need to dereference the "pv" pointer to access
// the struct's fields:
//
// YES: pv.x
// NO: pv.*.x
//
// We can write functions that take pointer arguments:
//
// fn foo(v: *Vertex) void {
// v.x += 2;
// v.y += 3;
// v.z += 7;
// }
//
// And pass references to them:
//
// foo(&v1);
The ziglings course goes quite in-depth on a few language topics, so it's definitely work checking out if you're interested.
With regards to other syntax: as the previous answer mentioned, you don't need to dereference array pointers. I'm not sure about anything else (I thought function pointers worked the same, but I just ran some tests and they do not.)
I'm working on a piece of code that use generics. This is an example of what I'm trying to achieve :
var strings: Array<Array<String>> = [["1", "2", "3"], ["4", "5", "6"]]
var array: Array<Array<AnyObject>> = strings
But the compiler says "'String' is not identical to 'AnyObject'".
I have no idea why the compiler complains and how to achieve what I need.
I already tried casting it like this :
var array: Array<Array<AnyObject>> = strings as Array<Array<AnyObject>>
Without any success.
Do you guys have any idea ?
Thanks.
That doesn't work because, as the compiler says, AnyObject is not String, although you can cast AnyObject to String and vice versa.
It doesn't even work using different value types that may seem "compatible":
var array1: Array<Array<UInt>> = []
var array2: Array<Array<Int>> = array1
The only way to do what you need is to write a converter that given an array containing object of type String returns an array of AnyObject.
The reason is that even if 2 data types are compatible, they do not use the same amount of memory and can have different data members and initialization constraints.
Taking into account that arrays are value types, the assignment is not done by reference - instead a copy of the array is created and assigned to the destination variable. If the underlying data type is the same for left and right side of the assignment, each item in the array can just be copied byte by byte to create a copy of it. If the left and right side have different types, that is not possible because most likely they use memory in a different way (i.e. they may have different data members), so in that case the object should be instantiated via an initializer, but which one and using which parameters?
I've learned that the As Long is much better than As Variant when it come to improving macro speed.
Dim data1() As Variant
data1 = Array("a", "b", "c", "d", "e")
Sheet1.ListBox1.List = data1
When I replace with As Long, my code doesn't work any more.
Your array doesn't contain Longs, it contains Strings. Try Dim data1() As String. (Don't worry - it's probably still faster than As Variant.)
While using explicit types is usually (almost always) better. This case is an exception because the List property of the ListBox is a Variant array anyway, so assigning a String or Long array to it causes an implicit type cast, so isn't any faster (and may even be slower).
What may make the difference is how you are loading data into the array before assigning it to the ListBox. If thats more efficient use explicit typed arrays then fine, use it.
BTW
Dim data1() as long
data1 = Array(1, 2, 3, 4, 5)
doesn't work because Array(...) returns a Varaint array which can't be assigned to an explicit typed array.