Semantics for shared structure



I have no formal background in CS, so I am not even sure I am framing this question right, but this comes up a lot in designing APIs for me.

Consider a simple type

immutable UsesNodes
    function UsesNodes(nodes)
        @assert issorted(nodes)
        new(nodes, calculate_value(nodes))

which checks the argument, and relies on it being not modified. nodes is created by the user, so in theory it could share structure and then be accidentally modified, as in

x = sort(rand(10))
u = UsesNodes(x)
# in a location far, far away
x[1] = 19.2 # seemed like a good idea

I can imagine two semantics:

  1. “paranoid”: always make a copy, maybe provide a constructor option that doesn’t,
  2. “trusting”: if you modify the value you have provided and your calculation breaks, it’s your problem.

I am trying to decide which one is more idiomatic for Julia, and have reviewed some code; but both approaches are present, eg WeightVec in StatsBase is “trusting”, but some packages have extra options for non-copying constructors.

Is there a general approach that would be a good default? I am leaning towards “trusting”.