Hello all,

A newbie here. I have been learning Nim using the online tutorials and is thoroughly enjoying Nim . I have completed the part 1 and have advanced to Part 2 of the tutorial. Have a question regarding the setter methods discussed in the 'Properties' section of the tutorial. Can you please help.

The code looks like this. It appears like s.host = 34 is not calling the setter proc. At the same time , s.`host=` 34 calls the setter proc.

Also is there a facility in Nim to mark class variables as Private/Public? Thanks in advance.

Edit - Aplologies, there was an error in my program, corrected now. My question still stands,

Nim Compiler Version 0.17.0 (2017-05-18) [MacOSX: amd64]

type
  Socket = ref object of RootObj
    host: int # cannot be accessed from the outside of the module due to missing star

proc `host=`(s: var Socket, value: int) {.inline.} =
  ## setter of host address
  echo "inside the getter host method"
  s.host = value

proc host(s: Socket): int {.inline.} =
  ## getter of host address
  s.host

var s: Socket
new s
s.host = 34  # => does not call the host= method. "inside the getter method" string is not printed
s.`host=` 34 # => works as expected. host= method is called.

2017-08-27 23:13:43
Aplologies, there was an error in my program, corrected now. My question still stands though. Thanks. 2017-08-28 06:04:44
The example from the tutorial is a bit misleading, try the updated version from the language manual instead. The host field of a Socket object is invisible to code from a different module, but the tutorial example code accesses it directly from within the same module with s.host = 34.
2017-08-28 11:13:27
@Lando, Many thanks for your reply, much appreciated. I was really confused. This is how I understand the concept from your reply. Please correct me if I am wrong.
  • if ' s.host = 34 ' is called from the same module, it will directly access the object variable bypassing the 's.host=' method/proc.
  • if ' s.host = 34 ' is called from a different module, 's.host=' method/proc is called as direct access to object variable is not allowed.
2017-08-28 11:34:25
Correct. This is why the name of the field was changed to something other than host in the updated example code.
2017-08-28 12:02:24
Thanks again @Lando for confirming this. It more clear to me now. Best Regards 2017-08-28 12:31:45
It seems to me it would be better to not allow a getter/setter to be named just like a private field. It's quite misleading. 2017-08-28 19:28:43
@Udiknedormi: I see how that would make sense. There is that ambiguity that a.host = 34 can mean two completely different things inside the module:
  • call the assignment operator
  • call a procedure named host=

But Nim seems to consciously embrace ambiguity to accomplish separation of concerns: I can write a.host in another module and not give a damn about whether this accesses a field or calls a proc which returns the value of a field and I like that. I don't want to know what encapsulation model the module I use has, I just want to use it. Much better than Java's getter/setter scheme.

Also having to use a tweaked field name inside the module would feel bad to me. Maybe a big fat ambiguity warning instead of an error would do.

A solution might be to make Nim reverse preferences in the above ambiguity: use the setter if there is one, else use the assignment.

Edit: of course the latter rule would need an exception for code inside the setter itself, which would be really strange.

2017-08-29 06:54:57

@Lando I think you misunderstood me. I like properties for the reasons you mentioned (mainly: not giving a damn). I just don't like the fact they work differently in the module the type is defined in.

As for whether properties are good: it depends. Memoized properties are often a good usecase: after the first access it actually is just a simple read (although one could argue that as the very first call is expensive, it should not mimic simple access). Also, properties can be an alias --- in one of my projects I used some generic N-spaces but aliased a few first elements of any N-dimentional array by x, y, z etc.

As for solution: why not use the same one as with assignments? system.`host=`(s, 34) sounds weird but hey, it IS weird to directly access a field when a setter for this field is defined!

2017-08-29 15:45:25