8 ms·
> When I looked at Julia last time I do not think it had the capability to partially apply tensors. In Spiral indexing into a 3d tensor would give you back a 2d
by StefanKarpinski 8y ago
> When I looked at Julia last time I do not think it had the capability to partially apply tensors. In Spiral indexing into a 3d tensor would give you back a 2d tensor. It might be possible to do this with function in Julia, but that would depend on its inlining capabilities and unlike Spiral it does not provide guarantees with regards to that.
That's exactly how slicing a tensor works in Julia:
julia> T = copy(reshape(1:2*3*4, 2, 3, 4));
julia> summary(T)
"2×3×4 Array{Int64,3}"
julia> T[:,2,:]
2×4 Array{Int64,2}:
3 9 15 21
4 10 16 22
Inlining seems irrelevant since the slicing is done eagerly. Unless you're talking about lazy slicing, in which case you could do `f(T) = T[:,2,:]` and your inlining/function comment makes more sense. If you use StaticArrays.jl (the closest thing in Julia to Spiral's tensors) then the machine code for this operation on a 2×3×4 Float64 tensor is just:
vmovups 16(%rsi), %xmm0
vmovups 64(%rsi), %xmm1
vmovups 112(%rsi), %xmm2
vmovups 160(%rsi), %xmm3
vmovups %xmm0, (%rdi)
vmovups %xmm1, 16(%rdi)
vmovups %xmm2, 32(%rdi)
vmovups %xmm3, 48(%rdi)
movq %rdi, %rax
retq
> Its type system is definitely less powerful than Spiral's - some of the things you could express naturally in Spiral would require macros in Julia.
The macro comment bit is a bit perplexing since macros are about syntax and are about as unrelated to the type system as it's possible to get. I'm unaware of any way that the presence of absence of macros in a language can affect the expressiveness of its type system.
I'd be very curious to hear what can be expressed in Sprial's type system that cannot be in Julia's. Julia's type system is generally more expressive than state-of-the-art dependent static type systems since it punts on type checking entirely. This allows it to have, among other things, parametric types where the parameters can be other types, integers, floats, symbols and tuples of same (recursively).Parametric types even support fancy features like using an earlier type parameters to constrain later type parameters, e.g. `X{T<:Number, S<:Vector{<:T}}` — i.e. `T` is a possibly abstract number type and `S` is a vector whose element type is a subtype of `T`.
The only major type system feature I'm aware of Julia lacking (aside from the obvious omission of static type checking) is intersection types. There's been some thought of adding those in order to support multiple inheritance among other things, but it hasn't proven necessary yet.
- abstractcontrol 8y agoI recall an example where Julia had to use macros in order to achieve loop unrolling. I'll dig it up if you want. This is something can be done quite naturally in Spiral due to its type system. I find that people often say macros are about syntax, but what they really are is some combination of a parser and a partial evaluator - in other words, their main use seems to doing compile-time function evaluation. Spiral does not have arbitrary CTFE, but can perform any functionally-pure, non side-effecting computation in its type system plus memoization of function calls. One thing of practical interest that makes me doubt Julia's inlining capabilities would be monads. https://github.com/pao/Monads.jl/blob/master/doc/index.rst https://github.com/pao/Monads.jl/blob/master/doc/index.rst "Monads.jl provides a powerful, if relatively slow" The key word here is slow. I haven't seen a single language as of yet apart from Spiral that can inline all their overheads away. They are pervasive in Haskell, and Haskell cannot do it. Scala wants to do it, but it can't. F# and Ocaml cannot optimize their overheads away. If Julia could then it would advertise it. This is something that is subject of academic research in the field of partial evaluation. Speaking as a functional programmer, as a language Julia feels barely functional to me. It has first class functions, but it does not have pervasive partial application and syntax that makes such a style comfortable like functional languages tend to have. It feels more like an imperative language. And speaking as a systems programmer, I know that without inlining guarantees you cannot have optimized functional constructs. It is not just monads. By tracking all the factions and their bodies to exactness and forgoing all heap allocation unless explicitly stated, it becomes much easier to do language interop. It is possible to make functions that capture variables from lexical scope and then pass as arguments to a function that passes them through to the GPU. Julia talks about speed, but barely talks about inlining so I am dubious about its claims. I could go on, but I think this is a large enough sample of my views on Julia. If Julia wants me to use it, then it needs to speak more to my values as a programmer.
- ChrisRackauckas 8y agoI agree that while Julia has a lot of functional programming elements, it's not strictly a functional programming language. It also is built for things where heap-allocated arrays are necessary: you're not going to be scientific computing with 100GB stack-allocated arrays. Having the base arrays be stack-allocated and then having StaticArrays for stack-allocated arrays works well, though that means you do want to use imperative styles a lot when managing the large array operations to cut down on allocations. Spiral and Julia are just very different and cater to different paradigms and applications.