Hey there,
Newbie here, i just started with Nim and i'm trying to port datetime from python. I was wondering if there is a way to set a mutable params in a procedure with default values?
So far i get "Error: for a 'var' type a variable needs to be passed"
type
Timedelta = ref object of RootObj
days: int
seconds: int
microseconds: int
hashcode: int
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: var int = 0): Timedelta =
new(result)
var d, s, us: int = 0
days = days + weeks * 7
seconds = seconds + minutes*60 + hours*3600
microseconds = milliseconds + milliseconds*1000
At least for latest Nim v 0.19 compiler tells you what the problem is:
type
Timedelta = ref object of RootObj
days: int
seconds: int
microseconds: int
hashcode: int
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: var int = 0): Timedelta =
new(result)
var d, s, us: int = 0
days = days + weeks * 7
seconds = seconds + minutes*60 + hours*3600
microseconds = milliseconds + milliseconds*1000
discard newTimedelta(1, 1, 1, 1, 1, 1, 1)
var a, b, c, d, e, f, g: int
discard newTimedelta(a, b, c, d, e, f, g)
t.nim(17, 21) Error: type mismatch: got <int literal(1), int literal(1), int literal(1), int literal(1), int literal(1), int literal(1), int literal(1)>
but expected one of:
proc newTimedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks: var int = 0): Timedelta
for a 'var' type a variable needs to be passed, but '1' is immutable
expression: newTimedelta(1, 1, 1, 1, 1, 1, 1)
First proc call with int literals does not work, but second call with actual variables work. When you think about it, it should be clear: When you pass int literals or consts, how should the proc be able to set the default values of parameters or change the parameters inside of the proc?
Oh i see,
In order to make it work though you will need to do it like this
type
Timedelta = ref object of RootObj
days: int
seconds: int
microseconds: int
hashcode: int
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: int = 0): Timedelta =
var days: int = days
var seconds: int = seconds
var microseconds: int = microseconds
var milliseconds: int = milliseconds
var minutes: int = minutes
var hours: int = hours
var weeks: int = weeks
new(result)
var d, s, us: int = 0
days = days + weeks * 7
seconds = seconds + minutes*60 + hours*3600
microseconds = milliseconds + milliseconds*1000
So if we use "var int" in the params, it is expecting a reference
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: var int): Timedelta =
# var days: int = days
# var seconds: int = seconds
# var microseconds: int = microseconds
# var milliseconds: int = milliseconds
# var minutes: int = minutes
# var hours: int = hours
# var weeks: int = weeks
new(result)
var d, s, us: int = 0
days = days + weeks * 7
seconds = seconds + minutes*60 + hours*3600
microseconds = milliseconds + milliseconds*1000
var r,s: Timedelta
var a,b,c,d,e,f,g: int = 7
r = newTimedelta(a, b, c, d, e, f, g)
echo a
echo b
echo c
echo d
echo e
echo f
echo g
So we wont get the original value after the proc has run
Hint: used config file '/home/luis/.choosenim/toolchains/nim-0.19.0/config/nim.cfg' [Conf]
Hint: system [Processing]
Hint: datetime [Processing]
CC: datetime
Hint: [Link]
Hint: operation successful (12309 lines compiled; 0.286 sec total; 16.395MiB peakmem; Debug Build) [SuccessX]
Hint: /home/luis/coding/nim/datetime/datetime [Exec]
56
25627
7007
7
7
7
7
https://nim-lang.org/docs/manual.html#overloading-resolution-overloading-based-on-var-t
https://nim-lang.org/docs/manual.html#statements-and-expressions-var-statement
Sorry but this is bugging me, I can't tell what your original code is trying to do, is this what you were trying to write originally?
type
Timedelta = ref object
days, seconds, microseconds, hashcode: int
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: int = 0): Timedelta =
new(result)
result.days = days + weeks * 7
result.seconds = seconds + minutes*60 + hours*3600
result.microseconds = microseconds + milliseconds*1000
Because this does not need var aliasing at all. Though I think 0.19 gives a warning when you don't initialize result, so maybe this is better:
type
Timedelta = ref object
days, seconds, microseconds, hashcode: int
proc newTimedelta*(days, seconds, microseconds, milliseconds, minutes, hours,
weeks: int = 0): Timedelta =
result = Timedelta(days: days + weeks * 7,
seconds: seconds + minutes * 60 + hours * 3600
microseconds: microseconds + milliseconds * 1000
Well the constructor needs those params but they wont be part of the object at the end, they will be normalized to seconds. What i was trying to accomplish is simply using the proc params as mutable variables. I didnt want to rename those vars because the names will be used extensevily. Does that make sense? I'm trying to port a standard lib written in python so im pretty much copying code so im getting used to Nim.
In other languages the arguments in the functions are normal vars in the scope of the function here however works a little dif ferent.
var means that you will mutate the input. It also means that the parameter being passed must be owned by an allocated variable in the calling context.
This is also called lvalue, it has a memory location and that can be mutated.
A literal "a" or "days = 10" doesn't own any memory and so cannot be mutated.