I have several times used the expression anArray.[i] to access an element from an array.
but all the sudden when i try to make a very very simple function then i get an error.
let safeIndexIf anArray i =
anArray.[i]
I need to make a function that returns the ith element of the array so i thought that was an easy one but no...
The Error:
The operator 'expr.[idx]' has been used on an object of indeterminate type based on information prior to this program point. Consider adding further type constraints
Why is this not working? I dont know what the error means by that. All i know i have done something similar to this lots of times to access an element of anArray so why can't i this time?
It means the compilers type inference cannot determine that anArray is indeed an array.
The error message is suggesting you add a type annotation, you could do something like this to say that anArray is a generic array:
let safeIndexIf (anArray : array<'a>) i =
anArray.[i]
If you want to avoid type annotations you could try rewriting your function to use Array.item which has the same behaviour:
let safeIndexIf anArray i =
Array.item i anArray
Related
The one with colorsArray.last works but not the one with the subscript syntax, e.g., colorsArray[2]. Any help you can give me with understanding this would be great. I'm learning Swift on my own so I come here to get my questions answered.
let colorsArray = ["Red", "Green", "Blue"]
if let method2 = colorsArray.last {
print(method2)
}
if let method2 = colorsArray[2] {
print(method2)
}
The issue is that with an array, the subscript operator does not return an optional, so it makes no sense to use an unwrapping construct like if let to unwrap it.
Try let foo = colorsArray[42], where the index is out of bounds. It doesn’t return nil, but rather will just crash with an “subscript out of range” error. As the documentation says (emphasis added):
Use the first and last properties for safe access to the value of the array’s first and last elements. If the array is empty, these properties are nil.
...
You can access individual array elements through a subscript. The first element of a nonempty array is always at index zero. You can subscript an array with any integer from zero up to, but not including, the count of the array. Using a negative number or an index equal to or greater than count triggers a runtime error.
So, the last provides safe access, returning an optional, but the subscript operator doesn’t return an optional, but also doesn’t provide safe access if you supply an invalid index.
If you will go to the documentation, you will find that when you use the Api last, the return type is optional, hence you can use optional binding to safely unwrap the value. But if you access the element by index like you are doing in the second case will give you the unwrapped value and compiler assumes that there will be a value for sure if you access like that. But keep in mind if your array size is less than the index you are passing then you may get error of array index out of bounds.
Unlike last the result of subscribing an array by index is not an optional.
let method2 = colorsArray[2]
print(method2)
The reason is most likely the ObjC compatibility, the disadvantage is if the index doesn't exist it throws an exception aka it crashes.
I'm doing a micro-optimisation of my LRU cache solution in Golang where I'm using https://golang.org/pkg/container/list/. My solution works by having a map[int]*list.Element, where each list.List list.Element is []int, with [0] being key, and [1] being value.
I'm trying to move from []int to [2]int for my optimisation, but I'm then running into the issue that modifying the fixed-size array, after ee := e.Value.([2]int) (note the [2]int type for fixed-size array), is no longer modifying the underlying values in the list.Element, unlike was the case w/ ee := e.Value.([]int) (note the []int type), which I guess makes perfect sense, since slices are based on references, whereas fixed-size arrays are based on copied values.
I've tried stuff like e.Value.([2]int)[1] = …, as well as various combinations with := &e.Value…, and casting from [2]int to []int, but it all results in complier errors.
Q: Is there no way to use the container/list with an embedded array, and perform modifications of said fixed-size array in-place?
As you already noted:
I guess makes perfect sense, since slices are based on references, whereas fixed-size arrays are based on copied values
So if you want to make this work, you'll need to use references to your fixed-size arrays by storing pointers to the arrays instead of array values.
That way, you'll be able to modify the underlying array through the list element.
See here for a simple example:
package main
import (
"container/list"
"fmt"
)
func main() {
l := list.New()
// create a fixed size array and initialize it
var arr [2]int
arr[0] = 1
arr[1] = 2
// push a pointer to the array into the list
elem := l.PushFront(&arr)
// modify the stored array
elem.Value.(*[2]int)[0] = 3
// print the element from iterating the list
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
// print the underlying array, both are modified
fmt.Println(arr)
}
EDIT
Note that this behaviour is not something specific to this list implementation, but rather related how type assertions work in the language itself.
See here:
https://golang.org/doc/effective_go.html#interface_conversions
Quoting from that section (and adding emphasis of my own):
The syntax borrows from the clause opening a type switch, but with an explicit type rather than the type keyword: value.(typeName) and the result is a new value with the static type typeName.
When using reference types, copying the value does not affect you cause copying a pointer value ends up allowing you to change the same underlying reference.
But when the array is a value itself, it does not make sense to assign to the copy. When you try to modify the array directly (without assigning the type assertion to a variable) Go would even catch this at compile time so that you don't assign to this "temporary" copy which would obviously be a mistake. That's how you got all your syntax errors when trying to do this.
To overcome this (if you don't want to use pointers) one possibility might be for you to implement your own list, borrowing from the implementation you are using but making your Element's value an explicit [2]int instead of an interface.
That would remove the need to make the type assertion and you'll be able to modify the underlying array.
I'm relatively new to C++, and I'm trying to take an array within a class, and set it equal to a passed in array.
public ref class Example {
array<float> ^ myarray1 = gcnew array<float>(3);
public:
Example(float^ myarray2) {
int i = 0;
while (i<3) {
myarray[i] = myarray2[i];
i += 1;
}
}
In the main function, the constructor is called as follows:
float myarray2[] = {1,2,3};
Example ^example1 = gcnew Example(*myarray2)
The errors I get is are as follows:
System::Single' has no default indexed property (class indexer)
expression must have pointer-to-object or handle-to-C++/CLI-array
type
Both of these errors are identified as happening where I am saying myarray[i] = myarray2[i].
I would greatly appreciate any help with solving this problem. I can't see where or how System::Single is getting pulled in as an error message. And, before it is suggested, I know I can get to work with setting myarray2 as a array float like myarray1, but I want it to work passing in myarray2 as float^ myarray2.
Since you say you're new to C++, let me point out that you're not writing classic C++ there. You're writing C++/CLI, which is a set of language extensions to C++ designed to interoperate with the CLI (.NET Framework). Because of this, the type float in your code is an alias for the type System::Single of the framework.
Regarding the indexer issue, the error messages pretty much spell out the cases in which you would be allowed to use an indexer:
System::Single' has no default indexed property (class indexer)
You could use an indexer if the type had a defined indexed property. System::Single, also known as float, doesn't happen to have one.
expression must have pointer-to-object type
You could use the indexer if the type was a non-void pointer type. You'd have to declare it like this:
Example(float* myarray2) {
In this case, myarray2[i] is equivalent to the expression *(myarray2 + i).
or handle-to-C++/CLI-array type
You could use the indexer if the type was a handle (^) to a C++/CLI array type. As you already know, you'd have to declare it like this:
Example(array<float> ^ myarray2) {
The bottom line is that, although you can treat a float* (pointer to float) like a C-style array of float (as a result of the rules of C and C++ about arrays and pointer arithmetic), these things simply do not apply to the float^ (handle to float) type (which is C++/CLI-specific).
Example(float^ myarray2)
That does not mean what you think it does. You are used to C language behavior, a float[] can automatically decay to a float* to the first element of the array. Somewhat unfortunately also carried forward into C++.
But not into C++/CLI, it is fundamentally unverifiable code. And responsible for a very large number of bugs and security problems. One core problem is that your constructor has no idea how many elements are stored in the array. You hard-coded "3" but if the caller passes an array that's smaller then Very Bad Things happen.
What it actually means is "reference to a boxed copy of a System::Single". The compiler tries to make sense of that, inevitably it starts to get very confused what you try to do next. Like using the [] operator, that requires the type to have an indexer. A float doesn't have one.
You need either:
Example(array<float>^ myarray2)
Which is safe and verifiable, you can't index the array out of bounds. And you don't have to hard-code "3" anymore, you can simply use myarray2->Length instead. And you don't (usually) have the copy the array anymore, simply assign myarray1. You'd call the constructor by passing gcnew array<float> { 1, 2, 3 }.
Or:
Example(float* myarray2)
Which works just like the way it does in C and C++. And required if you want to call the constructor with that float[]. Not verifiable, you need that magic "3". Do consider adding an extra argument to pass the array length.
What am I doing wrong? When I run this code in the playground I get the random element that is supposed to appear in the array, however there's an issue when I insert this code into my workspace project I get this error:
Expression resolves to an unused l-value.
var My-Array = ["Apple","Banana","Carrot","dewberry "]
My-Array[Int(arc4random_uniform(UInt32(My-Array.count)))]
This error tells you that the value that you get from your array is left unused. Playground lets you do it, because it is meant for playing with code. In production code, however, dereferencing an array and leaving the resultant value unused is a certain sign of an error.
To fix this problem, assign the value to a variable or a constant, or consume it in some other way (e.g. print it out):
let randomFruit = My-Array[Int(arc4random_uniform(UInt32(My-Array.count)))]
or
println(My-Array[Int(arc4random_uniform(UInt32(My-Array.count)))])
I'm trying to create a sparse array in Swift. I'm not sure if the problem is in my declaration (no syntax errors detected) or possibly a bug in beta 2?
I am trying to declare an array of 24 class instances as optionals. I then can fill in slots of the array as necessary. Here is the declaration:
var usage = WaterUsage?[](count:24, repeatedValue:nil)
This gets through the Xcode 6 beta 2 compiler without error. The intention is to end up with an array of 24 "WaterUsage" classes all set to nil.
When I try to set an array element:
usage[hour] = usage
where hour is < 24 I get the error:
"WaterUsage doesn't have a member named subscript"
I've also tried using generics but that doesn't appear to work either.
I find the Swift syntax for using optionals in complex data structures is a little obscure and could use some advice here.
That way of defining the array is giving you an Optional array of Optional values ( WaterUsage?[]? ), which you have to unwrap before you can use. I think you want just the values to be optional: WaterUsage?[]. One way I've been able to do that is by using the generic Array syntax:
var usage: WaterUsage?[] = Array<WaterUsage?>(count:24, repeatedValue:nil)
usage[hour] = something
Another way is to force unwrapping of the return value of your initial declaration. I don't know why, but WaterUsage?[]() has an Optional return value.
var usage = (WaterUsage?[](count:24, repeatedValue:nil))!
usage[hour] = something
You're pretty close! When using the MemberType[] syntactic sugar for arrays, the way that you wrote it (WaterUsage?[]) actually declares the Array as Optional, as well as the values that it holds. In which case, to assign a value to an index you would need to unwrap the Array first by using:
usage![hour] = someWaterUsage
However, if you only want Optional members in the Array (and don't want the Array itself to be optional), then you can fall back to the standard Array declaration:
var usage = Array<WaterUsage?>(count:24, repeatedValue:nil)
edit:
I originally offered an alternate syntax as another solution as well:
var usage = (WaterUsage?)[](count:24, repeatedValue:nil)
...but in doing so, per #Nate's observations it then becomes the case that you need to use unwrapping twice to access the value at a specific index, for example:
usage[0]!!.someProperty
this is just a shot in the dark, but I think what may be happening in this case is not dissimilar at all to what OP originally tried with declaring the Array using WaterUsage?[]
that is, when using (WaterUsage?)[], perhaps it is seeing this declaration as an Array of Optional Tuples holding Optional WaterUsages, requiring us then to unwrap the member at the index twice before we can access its properties
interesting stuff!