Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    rskar-git
    @rskar-git

    Wouldn't making X and Y read only be a better "signal" to the compiler...

    I have a feeling a real compiler/language designer would say "nope". Real world functions call other functions, and the lack of information on whether those other functions qualify as the "readonly" sort too would squelch any optimizations you might hope for wherever a compiler might otherwise detect a candidate "readonly" member. And even wherever one can get lucky via such tacitly inferred "signals", it'll only be of help to the assembly which contains them. The potential performance gains and memory pressure reductions dissipate once one needs to work through interfaces and other assemblies. Since real world applications often leverage libraries and frameworks, one would easily lose a lot of potential for all that compiler work. So an explicit "readonly" signal is essential for cross-assembly situations to maximize the potential improvements.

    The other reason for an explicit "readonly" signal is to minimize run-time surprises of adverse affects on performance and memory usage. Without an explicit "readonly" and compiler guidance, it may remain obscure as to why new or refactored code made things go poorer.

    ...the reason(s) for immutable are becoming much more visible/common, however the approaches do still feel a little "experimental"...

    That may be true enough for C# and .NET. Even so, the ways in which C++ uses its const keyword to effect its own "readonly" signals is an example of real world non-experimental usage (google on "c++ const correctness"). But no doubt the C#/.NET folks are thinking through on this.

    Cory Smith
    @DualBrain
    👍
    Mohammad Hamdy Ghanem
    @VBAndCs
    And finally, I started this to say that readOnly function is a confusing expression, and I prefer Preserve Functionwhich is a must in Preserve ReadOnly Property. But lets hope we need to debate about that someday :)
    CyrusNajmabadi
    @CyrusNajmabadi
    I think this protective copping is a big bug in the language design.
    why? if we don't copy, we would violate safety
    Mohammad Hamdy Ghanem
    @VBAndCs

    why? if we don't copy, we would violate safety

    Can you give an example?

    And how come that a property (which is actually a get function and a set sub) changes the fields of the struct without violating safty?
    CyrusNajmabadi
    @CyrusNajmabadi
    Can you give an example?
    uh...
    definitionally
    if it's readonly... the point is that it can only be read and not written...
    so if you were to mutate it... it would literally violate that
    CyrusNajmabadi
    @CyrusNajmabadi
    e.g. say i have struct Point { public int X, Y; }
    and i have readonly Point _point;
    it better not be possible to mutate _point
    Cory Smith
    @DualBrain
    Public Structure Point
       Public Sub New (x As Integer, y As Integer)
          Me.X = x
          Me.Y = y
       End Sub
       Public ReadOnly Property X As Integer
       Public ReadOnly Property Y As Integer
       Public Overrides Function ToString() As String
          Return $"{X}, {Y}"
       End Function
    End Structure

    To my knowledge the above is a "safe" Structure; where the only "annoyance" would be in the fact that I have to create a Newwhere it would be nice if the With functionality could initialize ReadOnly properties (I haven't attempted this lately, so don't know if it has changed recently to be allowed).

    There are also attributes that provide additional hints (StructLayout) to the compiler (and have been for ages) as to how to handle this structure (in the context of interop - I'm not sure they do anything outside of that scenario). To my knowledge this would be "pinnable" since it's only using blittable types (I could be wrong on this, but assuming...), so an array of this could be created outside of the main GC. (I haven't needed this scenario and the documentation seems a bit confusing on this subject - at least to me.)

    As for passing something like this by reference, that seems like trying to (at least to me) force something that (could potentially) be a value type, thus passable on the stack, into something that should be a reference type. And we already have this... if you want by reference, wouldn't that be a Class?

    Class <> Structure

    They serve two very different purposes and, although they appear to have similar functionality/purpose... they simply don't and we shouldn't try to force them to be "the same".

    Mohammad Hamdy Ghanem
    @VBAndCs
    @CyrusNajmabadi I erased my text as I got confused by @rskar-git example. The issue in his example comes from sending the struct to the String.Format function, which is a ByVal copy. Results will change if the sample is rewritten using string concatenation instead of Interpolated string. So, this is not a protective copy, This is a Val type vrs Ref type example.
    And it is a good point to treat structs in interpolated strings with caution if some parts of the interpolated string do some changes in the struct.
    CyrusNajmabadi
    @CyrusNajmabadi
    The issue in his example comes from sending the struct to the String.Format function, which is a ByVal copy.
    what do you mean?
    which string.Format overload.
    do you mean 'boxing'?
    And it is a good point to treat structs in interpolated strings with caution if some parts of the interpolated string do some changes in the struct.
    what interpolated strings mutate structs?
    Mohammad Hamdy Ghanem
    @VBAndCs
    I am talking about this sample:
    Structure CoordsStruct
    
        Public Shared ToStringCount As Integer = 0
    
        Public Sub New(x As Double, y As Double)
            Me.X = x
            Me.Y = y
        End Sub
    
        Public Property X As Double
        Public Property Y As Double
    
        Public Overrides Function ToString() As String
            ToStringCount += 1
            X += 1
            Return $"({X}, {Y}, {ToStringCount})"
        End Function
    
    End Structure
    
    Class CoordsCls
    
        Public Shared ToStringCount As Integer = 0
    
        Public Sub New(x As Double, y As Double)
            Me.X = x
            Me.Y = y
        End Sub
    
        Public Property X As Double
        Public Property Y As Double
    
        Public Overrides Function ToString() As String
            ToStringCount += 1
            X += 1
            Return $"({X}, {Y}, {ToStringCount})"
        End Function
    
    End Class
    
    Function Foo(ByRef oo As CoordsStruct) As String
        Return $"{oo}  {oo}"
    End Function
    
    Function Foo(oo As CoordsCls) As String
        Return $"{oo}  {oo}"
    End Function
    
    Sub Main()
    
        Dim cs As New CoordsStruct(3, 5)
        Dim cs_s1 As String = $"{cs}  {cs}  {Foo(cs)}"
        Dim cs_s2 As String = $"{cs}  {cs}  {Foo(cs)}"
        Dim cs_s3 As String = $"{cs}  {cs}  {Foo(cs)}"
    
        Dim cc As New CoordsCls(3, 5)
        Dim cc_s1 As String = $"{cc}  {cc}  {Foo(cc)}"
        Dim cc_s2 As String = $"{cc}  {cc}  {Foo(cc)}"
        Dim cc_s3 As String = $"{cc}  {cc}  {Foo(cc)}"
    
        Stop
    
    End Sub
    Dim cs_s1 As String = $"{cs} {cs} {Foo(cs)}" gives different results than
    Dim cs_s1 As String = cs & " " & cs & " " & Foo(cs)
    CyrusNajmabadi
    @CyrusNajmabadi
    why is ToString mutating? that violates badly anyones expectations on it.
    and if this was a readonly value, it should def have to copy then
    like... no types in the BCL will do this.
    Cory Smith
    @DualBrain

    why is ToString mutating? that violates badly anyones expectations on it.

    (A contrived example...)

    Mohammad Hamdy Ghanem
    @VBAndCs
    This was a @rskar-git sample about structs defensive copying
    CyrusNajmabadi
    @CyrusNajmabadi
    right. but we're nto going to warn people about formattable strings boxing things because someone might have a horrible ToString
    e.g. this statement:
    And it is a good point to treat structs in interpolated strings with caution
    i disagree. structs in interpolated strings are totally fine.
    it would be better ot say: if you do pathologically unrecommend things, then many things will not be happy.
    it's equivalent to saying: if you have a GetHashCode that continually changes values, you might have problems with a Dictionary :)
    Mohammad Hamdy Ghanem
    @VBAndCs
    It's not about ToString(). You can call any Method inside the {}, which can mutate the struct fields.
    I never did that though :)
    CyrusNajmabadi
    @CyrusNajmabadi
    that has nothing to do with {}
    that's the same anywhere.
    like var v = myStruct.Mutate();
    that's true inside {} or outside. nothing changes with that. teh method is called first, and the result value is what is passed into the interpolation.
    Mohammad Hamdy Ghanem
    @VBAndCs
    I mean inside interpolated strings
    CyrusNajmabadi
    @CyrusNajmabadi
    yes. that's what i'm saying
    that's true inside {} or outside. nothing changes with that. teh method is called first, and the result value is what is passed into the interpolation.
    :)
    Mohammad Hamdy Ghanem
    @VBAndCs
    But seems that repeated values are passed only once :)
    CyrusNajmabadi
    @CyrusNajmabadi
    i don't know what that means.
    Cory Smith
    @DualBrain
    Structures can pass on the stack (depending).