# Does anyone program like this?

**URL:** https://discourse.julialang.org/t/does-anyone-program-like-this/30328
**Category:** New to Julia
**Created:** [October 26, 2019, 8:44am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328 "2019-10-26T08:44:26Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)
#### Post date: [October 26, 2019, 8:44am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/1 "2019-10-26T08:44:26Z")

</div>

In chemistry we have the ideal gas Law PV=NRT

So do anyone program like this?

```julia
function CalcVIR(v::Union{Number,Missing},
                 i::Union{Number,Missing},
                 r::Union{Number,Missing})
    ''' If voltage is missing then calc v = i * r
        If current is missing then calc i = v / r
        If resistance is missing then calc r = v / i
    '''
    if ismissing(v)
        return i * r
    elseif ismissing(i)
        return v / r
    elseif ismissing(r)
        return v / i
    end
end

```

And using it like

```julia
Starting Julia...
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _ | |
  | | |_| | | | (_| | | Version 1.2.0 (2019-08-20)
 _/ |\ ___|_|_|\__ _| | Official https://julialang.org/ release
|__/ |

julia> v = CalcVIR(missing,3,5)
15

julia> v = CalcVIR(missing,3.4,5.6)
19.04

julia> i = CalcVIR(7,missing,3)
2.3333333333333335

```

---

<div class="post-metadata">

### Author: ![JonasIsensee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonasisensee/32/4704_2.png) [@JonasIsensee](https://discourse.julialang.org/u/JonasIsensee)
#### Post date: [October 26, 2019, 8:54am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/2 "2019-10-26T08:54:54Z")

</div>

Well, is there any advantage compared to writing the fraction explicitly?

---

<div class="post-metadata">

### Author: ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)
#### Post date: [October 26, 2019, 8:59am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/3 "2019-10-26T08:59:04Z")

</div>

I mean do people write function(s) that only returns the value of the missing parameter?

It’s how chemistry student uses the ideal gas Law in chemistry.

---

<div class="post-metadata">

### Author: ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)
#### Post date: [October 26, 2019, 11:04am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/4 "2019-10-26T11:04:57Z")

</div>

This doesn’t feel idiomatic to me since you’ll need to keep track what will be returned. I would probably assign the missing value and then `return v, i, r`

---

<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: [October 26, 2019, 11:53am UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/5 "2019-10-26T11:53:51Z")

</div>

I think I would prefer something like

```julia
complete_vir(v::Missing, i::Real, r::Real) = (v = i * r, i = i, r = r)
complete_vir(v::Real, i::Missing, r::Real) = (v = v, i = v / r, r = r)
complete_vir(v::Real, i::Real, r::Missing) = (v = v, i = i, r = v / i)

```

This way, it would be easier to avoid bugs from using the wrong variable accidentally from the output.

---

<div class="post-metadata">

### Author: ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)
#### Post date: [October 26, 2019, 12:19pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/6 "2019-10-26T12:19:24Z")

</div>

I might write it like this:

```julia
function CalcVIR(;v=missing, i=missing, r=missing)
    !ismissing(i) && !ismissing(r) && return i * r # i, r present 
    !ismissing(v) && !ismissing(r) && return v / r # v, r present 
    !ismissing(v) && !ismissing(i) && return v / i # v, i present 
    throw("Missing inputs ..") # 1 or 2 inputs missing 
end

```

and test different inputs:

```julia
julia> v = CalcVIR(i=3, r=5)
15

julia> i = CalcVIR(v=15, r=5)
3.0

julia> r = CalcVIR(v=15, i=3)
5.0

julia> v = CalcVIR(i=3)
ERROR: "Missing inputs .."
Stacktrace:
 [1] #CalcVIR#13(::Missing, ::Int64, ::Missing, ::Function) at .\REPL[32]:5
 [2] (::getfield(Main, Symbol("#kw##CalcVIR")))(::NamedTuple{(:i,),Tuple{Int64}}, ::typeof(CalcVIR)) at .\none:0
 [3] top-level scope at none:0

```

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [October 26, 2019, 12:56pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/7 "2019-10-26T12:56:19Z")

</div>

But how do you know which variable is being returned?

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [October 26, 2019, 12:56pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/8 "2019-10-26T12:56:57Z")

</div>

You could use keyword arguments as input and return a named tuple of all three.

---

<div class="post-metadata">

### Author: ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)
#### Post date: [October 26, 2019, 1:46pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/9 "2019-10-26T13:46:38Z")

</div>

The keyword inputs are named, so it is obvious that the missing one is being returned. I agree, however, that using a named tuple for outputs can be better.

Something like this:

```julia
function CalcVIR(;v=missing, i=missing, r=missing)
    !ismissing(i) && !ismissing(r) && return (v = i * r, i = i, r = r) # i, r present 
    !ismissing(v) && !ismissing(r) && return (v = v, i = v / r, r = r) # v, r present 
    !ismissing(v) && !ismissing(i) && return (v = v, i = i, r = v / i) # v, i present 
    throw("Missing inputs ..") # missing 1 or 2 inputs
end

```

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [October 26, 2019, 8:11pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/10 "2019-10-26T20:11:37Z")

</div>

Voting for @Tamas_Papp’s solution.  
Maybe even more idiomatic is to put such things into a struct that would always contain consistent values:

```julia
struct VoltCurRes{T<:Number}
    voltage::T
    current::T
    resistance::T
    function VoltCurRes(volt::V, cur::I, res::R) where {V<:Number, I<:Number, R<:Number}
        struct_type = reduce(promote_type, (V, I, R))
        new{struct_type}(volt, cur, res)
    end
end

VoltCurRes(volt::Missing, cur::Number, res::Number) = VoltCurRes(cur * res, cur, res)

VoltCurRes(volt::Number, cur::Missing, res::Number) = VoltCurRes(volt, volt / res, res)

VoltCurRes(volt::Number, cur::Number, res::Missing) = VoltCurRes(volt, cur, volt / cur)

```

Update: While the logic here is almost the same as with `ismissing()` checks, there is at least one logical and one performance-relevant difference.  
The logical difference is, the functions as written by Tamas and myself explicitly require exactly one missing argument and will give an error if there are more.  
The performance difference is that the type matching can be done at compile time while the `ismissing()` checks have to be done at runtime, which makes the version employing multiple dispatch faster in some cases.

---

<div class="post-metadata">

### Author: ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)
#### Post date: [October 26, 2019, 11:30pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/11 "2019-10-26T23:30:52Z")

</div>

I like your answer Vasily\_Pisarev

because in Electrical Engineering, the Voltages can be Real or Complex.

In fact having Imaginary Voltages is PERFECTLY normal in Electrical Engineering.

So the type Number is highly suitable for Electrical Engineering. This is why I use the type Number instead of the type Real or AbstractFloat in my julia code for the function CalcVIR.

---

<div class="post-metadata">

### Author: ![longemen3000](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/longemen3000/32/7298_2.png) [@longemen3000](https://discourse.julialang.org/u/longemen3000)
#### Post date: [October 26, 2019, 11:47pm UTC](https://discourse.julialang.org/t/does-anyone-program-like-this/30328/12 "2019-10-26T23:47:10Z")

</div>

i saw this on a matlab program to calculate psycrometric properties for humid air. in that case they take the parameters as keywords and returned all variables (calculated and specified). its used a lot in chemical engineering simulation. here is my two cents on how to do it:

```julia
#main function: the user should only see calculate_vir, 
#and not use the implementation calc_vir
calculate_vir(;v=missing;i=missing;r=missing) = calc_vir(v,i,r)
calc_vir(v::Missing, i::Number, r::Number) = (i*r,i,r)
calc_vir(v::Number, i::Missing, r::Number) = (v,v/r,r)
calc_vir(v::Number, i::Number, r::Missing) = (v,i,v/i)

```

Here is an interesting case, you can throw an error (overspecified), or try to calculate using some values (the cheapest calculation), it depends if your calculation comes from a system or it is user specified

```julia
#this comes from user overspecification
calc_vir(v::Number, i::Number, r::Number) = error("system overspecified")
#in this case, a tuple comes from a system calculation, so its reasonable to return the same tuple.
#you can add some checks if you want to be sure, in this case v≈i*r
calc_vir(vir::Tuple{Number,Number,Number}) = vir

```
