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


Reply via email to