# Inconsistency of type argument positions

**URL:** <https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [June 22, 2018, 11:59am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878 "2018-06-22T11:59:06Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 22, 2018, 11:59am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/1 "2018-06-22T11:59:06Z")

</div>

I happened to met the depwarn

> readstring(x) is deprecated to read(x, String)

And noticed some inconsistency. Note the following functions:

```julia
julia> parse(Int, "1234")
  1234

julia> floor(Int, 1.2)
  1

```

So, is `read(String, io)` make any sense?

* * *

edit: here’s what I found from the julia repo itself,

List1:

- `zeros(Int, N)`
- `getindex(Int8, 1, 2, 3)`
- `ceil(Int,N/2)`
- `reinterpret(Int, ccall(:jl_eqtable_nextind, Csize_t, (Any, Csize_t), a, i))`
- `map(Int,dims)`
- `bitcast(Int, x)`
- `convert(Int, sz)`
- `tryparse(Int, env_str)`
- `trunc(Int,x)`
- `round(Int, 1.7)`
- `floor(Int, log10(abs(x)))`
- `parse(Int, "1234")`
- `rationalize(Int, x; kvs...)`
- `unsafe_trunc(Int,n)`
- `tryparse(Int, env_cores)`
- `tryparse_internal(Int, sbuff, startpos, endpos, 0, false)`
- `ones(Int, 4, 4)`
- `typeparam(Int, rand(Int, 2))`
- `transcode(String, val)`
- `LibGit2.get(String, cfg, "branch.$branchname.remote")`
- `collect(Float64, 1:2:5)`
- `ounding.setrounding_raw(Float64, Rounding.JL_FE_TONEAREST)`
- `splitprec(Float64, i)`
- `Base.unsafe_convert(Int32, Base.cconvert(Int32, x))`
- `SparseArray(Float64, 3, 3)`
- `Base.sitofp(Float64, %9)`
- `rand(Float64,10,10)`
- `hilb(Float64,n)`
- `onediag(Float64, m, n)`
- `tridiag(Float64, m, n)`
- `sprand(Float64, 3, 0.75)`
- `spzeros(Float64, 3, 3)`
- `Base.typed_hcat(Float64, B, B, B)`

List 2:

- `empty([1.0, 2.0, 3.0], String)`
- ` read(`$shell -c "printf %s $(shell_escape_posixly(dir))"`, String)`
- `isa(s[2], String)`
- `similar(s, Int)`
- `rand(m, Int)`
- `π (%1, Float64)`

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [June 22, 2018, 12:51pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/2 "2018-06-22T12:51:47Z")

</div>

There’s been some discussion about this. The problem is that we have conflicting rules in this case, since we also usually put I/O streams as first arguments ~~so that the `do` syntax works (see e.g. `open`)~~ (EDIT: this is wrong, see below). IIRC it’s been decided that I/O streams take priority over return type parameters for that reason.

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 22, 2018, 1:01pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/3 "2018-06-22T13:01:37Z")

</div>

Okay, thanks for the info~

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 22, 2018, 1:04pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/4 "2018-06-22T13:04:30Z")

</div>

How about support these two forms simultaneously?

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [June 22, 2018, 8:43pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/5 "2018-06-22T20:43:10Z")

</div>

I thought it was functions that took precedence as the first argument because of the `do` syntax (`open` returns an I/O stream, but the body of the `do` becomes an anonymous function with is the first argument to `open`), not I/O streams.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [June 22, 2018, 8:45pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/6 "2018-06-22T20:45:12Z")

</div>

> [@innerlee](#):
>
> How about support these two forms simultaneously?

I’ve done that, in the `Strs.jl` package, where I wanted to support the `do` syntax, but the first argument was otherwise a Type, allow the function first or the type.

Scott

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [June 22, 2018, 9:25pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/7 "2018-06-22T21:25:29Z")

</div>

> [@ScottPJones](#):
>
> I thought it was functions that took precedence as the first argument because of the `do` syntax ( `open` returns an I/O stream, but the body of the `do` becomes an anonymous function with is the first argument to `open` ), not I/O streams.

Woops, yes, actually I confused `read` with `open`. We don’t actually care about passing the I/O stream as the first argument, that’s only useful for functions. So whether to pass the I/O stream or the type as first argument is mostly arbitrary.

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 23, 2018, 3:28am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/9 "2018-06-23T03:28:22Z")

</div>

Does it make sense to open an issue/pr on this? As in the first post, almost no function put type argument on non-first position

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [June 23, 2018, 3:33am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/10 "2018-06-23T03:33:15Z")

</div>

In this case, I think the more important factor is that the first argument (I/O stream or filename) is always needed, but the type to read it into is optional.  
I wouldn’t like to have to put `String` in 99% of the time, just to be consistent with the “rule” that the type should go first.

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 23, 2018, 3:41am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/11 "2018-06-23T03:41:12Z")

</div>

It is optional no matter at first or second position. Just like `floor`

---

<div class="post-metadata">

**Author:** ![nalimilan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nalimilan/32/147_2.png) [@nalimilan](https://discourse.julialang.org/u/nalimilan)\
**Post date:** [June 23, 2018, 8:25am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/12 "2018-06-23T08:25:01Z")

</div>

> [@innerlee](#):
>
> Does it make sense to open an issue/pr on this? As in the first post, almost no function put type argument on non-first position

But no function puts the I/O stream in non-first position either. You can’t satisfy both conventions at the same time.

---

<div class="post-metadata">

**Author:** ![innerlee](https://avatars.discourse-cdn.com/v4/letter/i/b19c9b/32.png) [@innerlee](https://discourse.julialang.org/u/innerlee)\
**Post date:** [June 23, 2018, 10:13am UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/13 "2018-06-23T10:13:29Z")

</div>

fine 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [June 23, 2018, 3:25pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/14 "2018-06-23T15:25:12Z")

</div>

The order is given in [official conventional argument precedence · Issue #19150 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/19150#issuecomment-320811138)

(idk if this is in the docs somewhere as well, it should be, if not that is an issue to open.)

Important part is: Jeff’s comment:

> I propose the following priority order (highest priority listed first):
> 
> 1. Function argument (for HOFs accepting one function, or for use with do blocks)
> 2. IO stream
> 3. Thing being mutated (Edit: to hold the main result of the computation)
> 4. Type
> 5. Collection (not being mutated)
> 6. Key
> 7. Value
> 8. Everything else
> 
> Exception: first argument to convert is always the type.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [June 23, 2018, 7:26pm UTC](https://discourse.julialang.org/t/inconsistency-of-type-argument-positions/11878/15 "2018-06-23T19:26:42Z")

</div>

I wonder why Jeff considered `convert` an exception?  
Type is `#4`, and Value is `#7`, so that follows Jeff’s list.  
I’m not aware of any `convert` methods that allow 1,2, or 3.

For `convert`, the ordering also makes a lot of sense given the similarity to constructors and the order that assignment works: `dest = source`, so `DestType(source)` or `convert(DestType, source)` all scan well.
