Regarding the `x::Int = 5` behavior, I just had a conversation with Jeff and Stefan yesterday where they helped me understand better how that works. My understanding certainly still may be flawed or incomplete, in which case I welcome corrections.
The syntax `x::Int` can mean a few different things depending on where it is: *LHS of an Assignment* When a type annotation is on the left-hand-side of an assignment, such as `x::Int = 5`, it declares x to be the given type, so all the code following that can be optimized with that assumption, and attempt to assign it to an incompatible value will throw an error. Additionally, julia attempts to convert the value on the RHS to the annotated type. The gotcha (and what I think David ran into), is that you can't do type annotations in the global scope (e.g. at the REPL). If you do it inside a function it works as expected. This limitation is mentioned at the end of this section<http://docs.julialang.org/en/latest/manual/types/#type-declarations>, but it's easy to miss and is definitely a gotcha. The snippet of the manual "Only values, not variables, have types — variables are simply names bound to values" seems wrong to me as well. It seems that in this usage the *variable* x is typed. Perhaps some heavier-hitting CS folks can shed some light? *Within an expression* Otherwise, within an expression x::Int is a type assertion, so for instance if I'm calling a function and I want to make sure that what I get back is a certain type, I can use `x = somefunc(10)::Int64`. Note that in this usage there is no conversion that happens, it just throws an error if the type doesn't match. This means you should make these annotations as liberal as you can (e.g. use Integer or Real, etc.), because if `somefunc(10)` returns an Int32 the above code would throw an error. *In a method declaration* The third meaning is within a method declaration, where you're providing information to the method dispatcher on when to call the given method. Note that this does NOT enforce the typed-ness of the variable as in the 1st syntax above. You're free to re-assign an argument variable and julia won't do any type checks or conversion. As far as I know this doesn't hurt performance though, because the code-gen knows what the type of the argument is, so as long as you don't reassign it the generated code is still able to assume the type. Also note that there is no conversion that happens here, either. For a method declared `function specificfunc(x::Int64)`, The method will simply not get called unless the argument is type Int64. For a method declared `function moregeneralfunc(x::Integer)`, The method will be called if the argument is any subtype of Integer, but the code will be generated on-demand to handle that specific data type. On Sat, Jan 25, 2014 at 10:14 AM, Leah Hanson <[email protected]> wrote: > I may miss parts of your email. It is more challenging to respond when you > dump many unrelated questions into the same email. (It would be easier if > you organized or numbered the different issues/comments, or reduced the > number of comments/email) > > Some of these, such as the arrow key thing, sound like they might be > better as a github issue. I don't know what the expected behavior on > windows is. > > For issues with the writing/content of the manual, the most effective > thing is to make a pull-request to make the changes. The source of the > manual is here: https://github.com/JuliaLang/julia/tree/master/doc/manual It's > convenient to edit them on github, especially if you're less comfortable > with git. (The workflow on github is remarkably smooth; all you need it a > github account.) I'm skipping things that sound like you just want a > specific change to the manual, since you can go make those. :) > > 1. I'm not especially experienced with intellisense (I don't use IDEs > generally), but Julia does know what methods are in scope at any given > point. If you're in the REPL or IJulia, you can type something like > `istext(` and then press Tab. It will show you a list of the methods of > `istext`. > > 2. As far as the undefined reference error, what needed to be changed > about the manual? It looks like it continues to behave as advertised. I > haven't dug into what the default printing function's implementation looks > like, but that would be where I'd look for how it gets around the undefined > problem. > > 3. Julia has first class types, so types are values in the language. Tuple > types are written as a tuple of the types, which seems fairly > straight-forward. Your version, Tuple{Int,Int}, would require a new type > for each size of tuple (or would have a different representation than you > suggested). I don't understand what you would gain by having a separate > type that basically reimplements the same functionality as a tuple. Could > you offer a concrete example of a problem this could cause? > > 4. "..." is called "splat" in Julia. > > 5. `x::Int = 5` evaluates both sides - `x::Int` and `5`. `x::Int` throws > that error because x is not defined yet -- it's definitely not an Int. If > you make it `5::Int`, you'll probably get closer to what you expected. > > More broadly, I think you have somewhat misunderstood typing/type > annotations in Julia. Type annotations (such as `x::Int`) are an assertion > that the preceding expression has the annotated type. These assertions are > used by the compiler for optimizations/type-inference, and create run-time > errors if the assertions fail. > Variables do not have types. In `x =5; x::Int`, the `::Int` annotation is > not checking or setting the "type of x"; it is checking the type of the > value of x. It doesn't make sense for it to work if x is not yet defined, > since x would have no value, and thus not have a type. > > It's possible that a longer code example may help you: > ~~~ > julia> x = 5 > 5 > > julia> x::Int > 5 > > julia> x::Int = 4.6 > 4.6 > > julia> typeof(x) > Float64 > > julia> x::Float64 > 4.6 > > julia> x::Int > ERROR: type: typeassert: expected Int64, got Float64 > ~~~ > > 6. There is only one implementation of Julia, so I'm not sure why you > wouldn't want "sizes are rounded up to multiples of 8 bits" in the manual. > It's useful if you care about the representation of your types in memory. > Since the manual can be updated at any time (such as to reflect a change in > implementation details), there isn't some lock in to the specification by > doing so. > > 7. I'm not going to answer your Tasks/produce question because I'm not > really familiar with Tasks. > > Best, > Leah > > > On Fri, Jan 24, 2014 at 8:09 PM, David Piepgrass <[email protected]>wrote: > >> I started learning Julia today so I have some random comments/questions. >> >> Firstly, Julia looks great. It is only the second dynamic language that I >> have ever seriously felt like using. The first dynamic language I liked was >> Ruby, until I came to appreciate the shortcomings of a dynamic language in >> large programs and in the general case, such as: >> >> - no compile-time detection for common (semantic) mistakes >> - no intellisense >> - even if you had intellisense you couldn't tell what types are accepted >> by a method (when a method is undocumented, having type information is >> vastly better than nothing!) >> - poor performance >> >> While I'm not sure if Julia can address the first problem very well, in >> other respects it seems superior to other dynamic languages. I use C# a lot >> and one of the best things about C# is its *perfect* intellisense, i.e. >> if the IDE shows a method, then I can call it, and if the the IDE does not >> show a method, it does not exist or it is inaccessible (there are >> exceptions, but none worth mentioning). I guess Julia can't have this kind >> of perfection, but perhaps it could come close under some circumstances... >> someday... right? >> >> Now, I'm on Windows and I noticed that pressing Ctrl+Any Arrow Key or >> Shift+Any Arrow Key causes the process to immediately terminate!! WTF >> - I hoped Shift+Left would select one character and Ctrl+Left would move >> one word to the left. >> >> In the manual, in Control Flow it says: "Exceptions can be created >> explicitly with throw." I think this should say "Exceptions can be raised >> explicitly with throw." An expression like DomainError() *creates* an >> exception, yes? >> >> The section on Tasks begged a question. What happens when I do this? >> >> julia> function producer() >> produce("1"); >> produce("2") >> end >> producer (generic function with 1 method) >> >> julia> producer() >> >> julia> # what did I just do??? >> >> http://docs.julialang.org/en/release-0.2/manual/types/ says: >> >> >>> - Only values, not variables, have types — variables are simply >>> names bound to values. >>> >>> >> Huh? I'm pretty sure variables can have types, otherwise how could Julia >> optimize "x::Int8" into 1 byte and store it efficiently? It's confusing to >> claim variables do not have types when everything else I've seen tells me >> they do. In fact, the possibility of assigning types to variables (and not >> just values) is one of the greatest advantages of Julia over other dynamic >> languages. So to say that variables do not have types is as >> counterproductive as it is confusing. >> >> We are told bits types must be a multiple of 8 bits. Why? I can see >> multiple reasons why Julia would internally round up sizes to multiples of >> 8, but it seems like a mere "implementation detail". Why require the formal >> definition to say, for instance, that Bool is 8 bits? >> >> We are told about incomplete initialization in >> http://docs.julialang.org/en/release-0.2/manual/constructors/ : >> >>> Although it is generally a good idea to return a fully initialized >>> object from an inner constructor, incompletely initialized objects can be >>> returned: >>> >>> type Incomplete >>> xx >>> >>> Incomplete() = new()end >>> julia> z = Incomplete(); >>> >>> While you are allowed to create objects with uninitialized fields, *any >>> access to an uninitialized field is an immediate error*: [emphasis mine] >>> >>> julia> z.xxaccess to undefined reference >>> >>> When I saw this I was puzzled because this behavior would seem to block >> Julia's famed optimization capabilities. I was not surprised to find out >> that the manual is incomplete and should be changed: >> >> julia> type Some{T} >> value::T >> Some()=new() >> Some(v::T)=new(v) >> end >> >> julia> Some{Int}() >> Some{Int64}(0) >> >> julia> Some{Int}() >> Some{Int64}(237821312) >> >> julia> Some{Int}() >> Some{Int64}(125) >> >> julia> Some{Integer}().value >> ERROR: access to undefined reference >> >> julia> Some{Integer}() >> Some{Integer}(#undef) # did printing that secretly involve catching an >> error? >> >> That reminds me, the Julia manual doesn't mention the syntax of comments, >> nor does it use any comments for the first 6 chapters since it's all REPL. >> So I figured out the comment syntax by guessing. >> >> I hate 1-based indexes. Eww. I know it's not going to change at this >> point... I'm just sayin'. I thought in modern times the question had been >> settled. >> >> The way that types-of-types work in Julia strikes me as kind of >> bizarre. So some tuples are types and others are not types? I just have to >> say, wow! That's something else. It's a bit shocking to see the base >> language and metalanguage/reflection mixed like that. I sort of see the >> advantage, that you can express a tuple's type very simply as e.g. (Int, >> Int) rather than, say, Tuple{Int, Int}. But wouldn't there be disadvantages >> to this in reflective code? This particular magic just makes me feel... >> uneasy. >> >> When introducing the peculiar syntax (::Type{T}, x::Number) in >> http://docs.julialang.org/en/release-0.2/manual/conversion-and-promotion/, >> I think the manual should mention that this basically means >> (unused::Type{T}, x::Number) except that a variable is not defined. The >> manual might have explained this syntax earlier, I don't know - users >> shouldn't have to read and remember the whole manual from the beginning. >> Similarly I think it bears repeating that "..." (e.g. in >> +(promote(x,y)...)) is the "splicing" operator. >> >> The Types chapter neglects to mention that (Foo,) is the syntax for a >> one-tuple. The very concept of a one-tuple might be foreign to some >> readers; for those that know of it, it may not be immediately obvious that >> "(Real,)" is a 1-tuple, rather than a 2-tuple in which the second value is >> somehow missing or empty. >> >> Why doesn't this work? >> >> julia> x::Int = 5 >> ERROR: x not defined >> >> Okay, I think that's enough random stuff for now. G'day mates! Cheerio! >> > >
