Hi, In this post <https://groups.google.com/d/msg/julia-users/8nl6ApB4nag/2XgQ11sXCwAJ>, I was a little surprised to see Numbers treated in some sense as containers with partially implemented container operations, etc. Glen posted a great comment highlighting some issues:
On Wednesday, 2 December 2015 11:38:50 UTC+10, Tim Holy wrote: >> Conversely, there are many people who seem to want Julia to treat scalars >> and 1-vectors indistinguishably (ala Matlab). > > Sure, but it should be one way or the other, not half way between. In > Matlab, scalars are literally 1-vectors, so everything that works with > 1-vectors works with scalars. In Julia, some things work, and others don't. > That just results in confusion. > As an example, reshape(1,1) throws an error, and squeeze(1,(1,)) gets stuck > in an infinite loop. vec(1) throws an error, as does cumsum(1). And of > course there's the issue with getindex involving colon, arrays or ranges > for indexing (you'd think that, just as a[[1,1]] gives the value of a[1] > twice for an array, that it would do the same for a scalar, but it doesn't). > I can understand the desire not to have them be identical (since there are > cases where a function should do a different thing for a number than it > does for an array), yet allow partial compatibility... it's just a little > arbitrary which cases work and which don't. Regarding Glen's last sentence, this could be obtained, if desired, by making Number <: AbstractArray. However, I can imagine the appetite for doing that is approximately (and rightly so) zero. In my opinion, Numbers are scalars and should not have a getindex or any related array operations that Glen highlights are largely broken anyway. However, one of the beautiful things about Julia is that it is designed to allow you to "do what you want". I want indexing a Number or attempting to use a Number as an iterator to be an error so I created strict.jl <https://github.com/EricForgy/strict.jl>. This is motivated by strict mode <https://msdn.microsoft.com/en-us/library/br230269%28v=vs.94%29.aspx>, i.e. "use strict", in JavaScript. So now, in Julia, you can call: using strict This gets you a subset of Base that, for the moment, simply kills some of the array operations on Numbers, but I hope to grow this by killing any softer corners in Base where some compromises seem to be made. Along with "strict", I was also thinking of having a corresponding using nonstrict This wold basically resurrect any functionality that is killed by "using strict". One idea is that this might pave the way for eventually removing some of the fat from Base to make debugging easier, etc., but still making the functionality available if someone wanted it, e.g. if someone wants getindex for Numbers, they could do something like: import nonstrict: getindex(x::Number) Some responses to questions/comments in the other thread: On Wednesday, December 2, 2015 at 9:11:32 PM UTC+8, Seth wrote: This is great. I assume it catches "for i in n" where n is a scalar, also, right? Yes. If I understand correctly. This is based on "Number", so it will catch anything that inherits from Number. On Wednesday, December 2, 2015 at 9:47:44 PM UTC+8, Steven G. Johnson wrote: > On Tuesday, December 1, 2015 at 9:38:46 PM UTC-5, Eric Forgy wrote: > Then again, I wish Julia had a "strict" mode. In strict mode, the language >> would be more pure mathematically, e.g. scalars have no indices, the >> transpose of a vector is a covector, etc. >> > > Not all vectors represent elements of a Hilbert space, and not all 2d > arrays represent linear operators. [snip] > Although when I read your comment it sounds like you are disagreeing with me somehow, I actually agree with everything you said and don't see anything I said that contradicts what you said either. Peace? :) On Thursday, December 3, 2015 at 1:51:35 AM UTC+8, Cedric St-Jean wrote: > There's also > > x = [1 2; 3 4] > x[:,[1]] # returns 2D array > x[:, 1] # returns 1D array > x[1, :] # AFAIK, returns 2D under Julia 0.4 and 1D under 0.5 > > I like the 0.5 behaviour a lot better. > Really? I haven't tried 0.5 yet, but if x[1,:] is a 1D array, what happens if you try x[1,:]*A where A is a 2 x 3 matrix? It certainly works in 0.4 and would be hard to imagine not working in 0.5. This is why I like "covector" or "dual vector" or "linear form" or even "row vector". Anything other than "vector" :) On Wednesday, December 2, 2015 at 10:20:39 PM UTC+8, Tim Holy wrote: > On Wednesday, December 02, 2015 05:11:32 AM Seth wrote: > I could see requiring this by default in all my packages. > > Might be better as a test dependency, since it works by "breaking" methods > in Base. If you include it in your package by default, you risk fragmenting > Julia into incompatible dialects. Similar to JavaScript "strict mode <https://msdn.microsoft.com/en-us/library/br230269%28v=vs.94%29.aspx>", this fragmentation is part of the purpose. I like this answer <http://stackoverflow.com/a/8651441> on SO about JavaScript's strict mode that is in similar spirit to strict.jl Its main purpose is to do more checking. Just add "use strict"; at the top of your code, before anything else. For example, blah = 33; is valid JavaScript. It means you create a completely global variable blah. But in strict mode its an error because you did not use the keyword "var" to declare the variable. Most of the time you don't mean to create global variables in the middle of some arbitrary scope, so most of the time that blah = 33 is written it is an error and the programmer didn't actually want it to be a global variable, they meant to write var blah = 33. It similarly disallows a lot of things that are technically valid to do. NaN = "lol" does not produce an error. It also doesn't change the value of NaN. using strict this (and similar weird statements) produce errors. Most people appreciate this because there is no reason to ever write NaN = "lol", so there was most likely a typo. Read more at the MDN page on strict mode Similarly, although there are probably valid uses, if you try to index into a Number or use a Number as an iterator, I think it is probably an unintentional error that is difficult to catch. In this case, "using strict" might help. Cheers PS: Here is an example from the other thread: julia> n = 5 5 julia> for i = n println(i) end 5 julia> using strict julia> for i = n println(i) end ERROR: MethodError: `start` has no method matching start(::Type{Number}) in start at C:\Users\Eric Forgy\.julia\v0.4\strict\src\strict.jl:24
