# Hints for an old programmer new to Julia

**URL:** <https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606>\
**Category:** General Usage\
**Created:** [December 12, 2018, 6:11pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606 "2018-12-12T18:11:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![peter.wolf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peter.wolf/32/6018_2.png) [@peter.wolf](https://discourse.julialang.org/u/peter.wolf)\
**Post date:** [December 12, 2018, 6:12pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/1 "2018-12-12T18:12:00Z")

</div>

First, let me say I love Julia! It is a terrific new tool in my box for Machine Learning 😃

I am an old time programmer who is used to type safety and static type checking, and with Julia, I am experiencing many of the same frustrations I have with Python-- namely when I try to use someone else’s code, it can be a bear.

For example, I am currently using Flux to do some NLP. I want to make a text classifier using a Conv layer. I feed it my word embeddings and get a mystery crash deep inside NNLib. Obviously I am not passing it the kind of input it expects. The Flux code has no argument types, and the comments do not mention types. I waste huge amounts of time trying to reverse engineer the stack dump and guess what I did wrong.

For reference, here is the code

```
Data should be stored in WHCN order. In other words, a 100×100 RGB image would                                                      
be a `100×100×3` array, and a batch of 50 would be a `100×100×3×50` array.                                                          

function (c::Conv)(x)
  # TODO: breaks gpu broadcast :(                                                                                                   
  # ndims(x) == ndims(c.weight)-1 && return squeezebatch(c(reshape(x, size(x)..., 1)))                                              
  σ, b = c.σ, reshape(c.bias, map(_->1, c.stride)..., :, 1)
  σ.(conv(x, c.weight, stride = c.stride, pad = c.pad, dilation = c.dilation) .+ b)
end

```

This is not a complaint about Flux (which I love). I have the the same problems with most libraries in Julia and Python

- Without something like Traits or Interfaces it is hard to know what one should pass as arguments
- You don’t find out your mistake until runtime, often after things have been running for a while
- The error is usually some stack dump that starts way down in a library called by a library called by… your code

I end up in the REPL trying different things to see what works

How can I be more productive?

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [December 12, 2018, 6:41pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/2 "2018-12-12T18:41:07Z")

</div>

There is definitely a tension here between flexibility (often obtained by not specifying the types of arguments of functions), and type-checking and legibility of the interface.

---

<div class="post-metadata">

**Author:** ![jonathanBieler](https://avatars.discourse-cdn.com/v4/letter/j/82dd89/32.png) [@jonathanBieler](https://discourse.julialang.org/u/jonathanBieler)\
**Post date:** [December 12, 2018, 7:33pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/3 "2018-12-12T19:33:33Z")

</div>

It looks to me like `x` should be typed as `AbstractArray` at least, since it’s using `size` (which is part of `AbstractArray` [interface](https://docs.julialang.org/en/v1/manual/interfaces/index.html#man-interface-array-1)).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 12, 2018, 7:36pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/4 "2018-12-12T19:36:17Z")

</div>

> [@peter.wolf](#):
>
> code has no argument types, and the comments do not mention types

This, to a certain extent, is a side-effect of Julia being so generic. With multiple dispatch, you usually don’t restrict to a specific set of types, as anything that respects the interface (more on this below) will work. Eg this can be used to extend functions written in pure Julia with [AD](https://github.com/JuliaDiff/ForwardDiff.jl) or [interval arithmetic](https://github.com/JuliaIntervals/IntervalArithmetic.jl), even when these functions were not written with this in mind.

The downside is that interfaces are not formally defined, and even if some have some recognized [conventions](https://docs.julialang.org/en/v1/manual/interfaces/) this is not explicitly enforced by the language. A non-working program could then be a mistake on the programmer’s part, a bug in eg Flux, or some corner case of the interface which no one explored so far.

My usual strategy is to make a self-contained minimal example of the bug (which you should do), and ask here, then open an issue.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [December 13, 2018, 8:11am UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/5 "2018-12-13T08:11:48Z")

</div>

I’ve been playing with Flux recently and it’s been a lot of fun. But also slightly frustrating because being a rather experimental package it’s in a state of flux itself, and the internals are only very lightly documented at the moment. (Not to complain; my own packages suffer from many documentation problems of their own.)

For Flux specifically, I found it very helpful to build up my Flux models interactively in the REPL with a “toy sized” batch of data. This can be done incrementally, adding one layer at a time until the shape of the data matches correctly between layers. The loss function and a single step of an optimizer can be tested in a similar way. Once all this is working I would try a training run on some medium sized example data.

On a meta level, I think it’s useful to pursue the tightest feedback loop possible for experimentation and discovery, and this is where the interactive environments which can be created using python and julia really shine. It’s that qualitative difference in creativity which comes with having the result right now, rather than in five minutes after recompiling and reloading the data. But there’s a cost for production code bases compared to static languages, which seems to come in the form of more tests. Things which the compiler doesn’t test for you inevitably need to be tested manually.

Coming back to your original problem, yes we don’t have interface definitions in the language and this leads to a large amount of duck typing. Right now, I don’t think there’s a better solution than clear API documentation. Type constraints on functions is a non-solution in general because the type tree (being a _tree_) often can’t capture the full set of types a function will work on (\*). Amusingly this is exactly the same problem faced by C++ template libraries which use trait-based dispatch rather than normal class inheritance. These C++ libraries fail in exactly the same way you’re experiencing: deep within the implementation in a place the user should never see (witness, eg, something like `boost::iostreams`)! The problem isn’t solved there either as C++ concepts have been rejected from the last several standards.

(\*) Yes, `Union`s can help out here, but are inherently non-extensible. Manually defined traits help and are extensible, but are often clumsy to use.

---

<div class="post-metadata">

**Author:** ![peter.wolf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peter.wolf/32/6018_2.png) [@peter.wolf](https://discourse.julialang.org/u/peter.wolf)\
**Post date:** [December 13, 2018, 2:46pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/6 "2018-12-13T14:46:27Z")

</div>

Thank you Chris, Tamas, Jonathan and Petr. That is exactly the kind of advice I was looking for. I will concentrate on building up small things in the REPL.

I like the flexibility of Julia, and use it in my own code. But it sure would be nice if there was some optional way to declare ‘contracts’

For example, in the case of Flux.Conv it seems to only work for 2d convolutions and AbstractArray data that is of dimensions [w,h,d,n], so if you have a single grey scale image, you have to reshape it as [x,y,1,1]. Furthermore, while Conv works on TrackedArrays, operations like transpose on TrackedArray causes a stack dump. I guess the return of transpose(TrackedArray) is no longer an AbstractArray. It sure would be nice if the compiler could optionally catch that sort of thing.

In any case, this sure beats working in C++ 😃

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [December 13, 2018, 3:12pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/7 "2018-12-13T15:12:44Z")

</div>

> [@peter.wolf](#):
>
> But it sure would be nice if there was some optional way to declare ‘contracts’

This may eventually emerge, but perhaps not in the short run because of other priorities. In the meantime you can keep an eye on

> <https://github.com/JuliaLang/julia/issues/6975>
>
> I think this feature request has not yet its own issue although it has been disc…ussed in e.g. #5.
> 
> I think it would be great if we could explicitly define interfaces on abstract types. By interface I mean all methods that have to be implemented to fulfill the abstract type requirements. Currently, the interface is only implicitly defined and it can be scattered over several files so that it is very hard to determine what one has to implement when deriving from an abstract type.
> 
> Interfaces would primary give us two things:
> \- self documentation of interfaces at a single place
> \- better error messages
> 
> Base.graphics has a macro that actually allows to define interfaces by encoding an error message in the fallback implementation. I think this is already very clever. But maybe giving it the following syntax is even neater:
> 
> \`\`\`
> abstract MyType has print, size(::MyType,::Int), push!
> \`\`\`
> 
> Here it would be neat if one could specify different granularities. The \`print\` and \`push!\` declarations only say that there have to be any methods with that name (and \`MyType\` as first parameter) but they don't specify the types. In contrast the \`size\` declaration is completely typed. I think this gives a lot of flexibility and for an untyped interface declaration one could still give quite specific error messages.
> 
> As I have said in #5, such interfaces are basically what is planed in C++ as \`Concept-light\` for C++14 or C++17. And having done quite some C++ template programming I am certain that some formalization in this area would also be good for Julia.

and related issues.

---

<div class="post-metadata">

**Author:** ![peter.wolf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/peter.wolf/32/6018_2.png) [@peter.wolf](https://discourse.julialang.org/u/peter.wolf)\
**Post date:** [December 13, 2018, 3:40pm UTC](https://discourse.julialang.org/t/hints-for-an-old-programmer-new-to-julia/18606/8 "2018-12-13T15:40:53Z")

</div>

Perfect! I see that this issue has been discussed from the beginning, and bigger minds than mine has pondered it.

I will +1

```
What we do care about is allowing people to document the expectations of a 
protocol in a structured way which the language can then dynamically verify
(in advance, when possible).

```

and now I will go watch the Guy Steele talk
