> someList(0) /* instead of */ someList[0]
This is worse. How do you disambiguate that from a function call? It's now just abusing ()
> someList(0) /* instead of */ someList[0]
This is worse. How do you disambiguate that from a function call? It's now just abusing ()
You don't. If you apply an integer to an array, it will return an entry. To me, it makes perfect sense to use a(i) instead of a[i]. In fact, in case you need some more complicated data structure to organise your data one day, you could switch to a function call for lookup without rewriting the code that uses a(i).
The question is not 'how do you disambiguate?', but 'why do you want to distinguish?' Because an array is just a special case of a function that maps an integer to something else. It is logically not different from a function with a large contiguous switch statement.
I disagree. Square brackets links to memory, paren just returns data. Of course you could implement the paren function to return a reference, but it makes the code a lot harder to read since that is not the normal case. See comparison:
a[i] = 3;
or a(i) = 3; foo = [10,20]
Func foo(i) = switch(i)
case 0: return 10
case 1: return 20
default: return nil fn someArray(offset: usize) -> T* {
self.base + (offset * T.size) as T*
}That is, the cardinality of the type Array<T> is exactly the same as the cardinality of the type Function<Integer, T>. Any pure function that takes an integer and returns T can be replaced with an array, and vice versa.
Same deal with Map<K, V>, that's logically equivalent to Function<K, V>.
Two problems:
1. People don't think in category theory, they have containers to contain thinks and functions to calculate things.
2. People are right, the function call really is doing something different than an array index. If a thing is different, it should look different.
What is fundamentally different?
About the only reason I can see for array access syntax existing is that in the days before optimizing compilers, people would have lost their mind if array access called into a function each time (with good reason). It took manual programmer intervention to hint what compilers couldn't cleanly infer themselves. We don't need that anymore.
While they are mathematically equivalent, in these languages they are doing different things. Function application and array access are two different concepts the symbols are trying to convey to a programmer.
This is why, e.g., in Haskell where a string is literally a list of characters, they nevertheless have a different syntax for the two.
> Haskell provides indexable arrays, which may be thought of as functions whose domains are isomorphic to contiguous subsets of the integers.
https://www.haskell.org/onlinereport/haskell2010/haskellch14...
The fact that strings are different seems to have more to do with the ergonomics of strings rather than arrays.
If we limit ourselves to the math, we can agree that a type is a domain that contains certain values and excludes others. But we have to throw out mutability because values, by mathematical definition, are immutable.
And once we've got a clear notion of what values are, we can then talk about how many values there are in a type. And that's where I'm coming from in claiming functions are equivalent to containers.
If I'm adding shifting to a new language, I'm inclined to use functions just so it's clear what's going on, and to put operations like rotation on an even footing. Also, I don't think people have an intuition for the precedence of shift operators, which makes them less useful.
The article proposes using basic function call syntax. That makes no sense to me. And with .(), you now have 3 characters to type instead of 2 with []. Obviously all of this is pedantic, but then again so is the article.
I've written a decent amount of Scala, it's fine.
I've also written a lot of Common Lisp, where array access is done using aref. That was also fine.