Re: Why does the this code work?

2020-02-19 Thread lscrd
I have tried to declare a `varargs[string | seq[string]]` but the compiler 
rejects it. It seems that for `varargs`, more strict rules apply to avoid some 
nasty problems.

But there may exist other problematic cases as Araq said. Adding – in a future 
version – an explicit unpacking as he suggests would simplify things (and 
Python people would say that explicit is better than implicit). Personally, I 
would not care as I have never used this feature, but `unpackVarargs` is really 
an ugly name :-).


Re: Why does the this code work?

2020-02-19 Thread Araq
I'm sure there a couple of open bugs thanks to these rules and in retrospect 
`f(unpackVarargs(s))` might have been the better design. Maybe for Nim version 
2. :-)


Re: Why does the this code work?

2020-02-18 Thread cumulonimbus
You're right, thanks; There probably could be issues in convoluted cases (will 
try to construct one later for fun, e.g. `varargs[string | seq[string]]` , or 
with default conversions -- but you're right that this is unlikely to ever 
pop-up om regular use even if these cases can artificially be constructed.


Re: Why does the this code work?

2020-02-18 Thread mratsim
> Varargs has to be the last parameter, openarray(s) can be anywhere.

Actually they also can be anywhere.

Caveat: `varargs[untyped]` in macros (specifically not `varargs[typed]` and not 
in template) have a bug and are currently only usable as the last parameter.


Re: Why does the this code work?

2020-02-18 Thread lscrd
As regards implicit dereferencing, the compiler, when looking for the field "a" 
has to detect that "p" is a reference or a pointer, check if the referenced 
type is an object or a tuple and that it contains a field "a" and if this is OK 
generate the code for dereferencing. I don’t see that as stylistic. Other 
languages will detect an error as "p" has not the right type.

As regards the varargs, that Python has more information at runtime than Nim, I 
agree. But, the expansion has to be done at compile time, not at runtime and 
Python lacks information about the expected argument type. When you write `def 
f(x):`, you don’t give the compiler a clue about the type of the elements of 
"x" which may be a list, an int, an dict and so on. So, if I call it with a 
list (without the "*"), the compiler cannot do the expansion as it doesn’t know 
what is expected (and to complicate things, contrary to Nim, the varargs need 
not to be of the same type).

And your example with `printStuff(@[lines]` is wrong. If you want to pass a 
list of strings as a whole to a varargs, you have to declare the procedure to 
accept a sequence of strings, not a string. "printStuff" has been declared to 
accept a `varargs[string]` not a `varargs[seq[string]]`, so, when writing 
`printStuff(lines)` there is no way you can get a unique argument "lines" as it 
has not the expected type "string".

But this works:


proc printStuff(x: varargs[seq[string]]) =
  for element in x:
echo element

let lines = @["abc", "def"]

printStuff(lines)



Run

Comparing Nim and Python is frequently a bad idea as the languages are 
fundamentally different. Python has done things a way which is logical for a 
dynamically typed language. And Nim does the things another way which is 
consistent with its nature.


Re: Why does the this code work?

2020-02-18 Thread cumulonimbus
> There is another case where the Nim compiler uses its knowledge of types to 
> help the programmer: this is the automatic dereferencing of references and 
> pointers.

No, it's just a stylistic decision, one that some people find surprising as it 
is a special case.

Python could have just as well automatically expanded a list into varargs - in 
fact, it has more information at the time of the call than Nim does, being 
dynamic.

If you want to pass just one list argument to a vararg Nim proc, you need to 
call e.g. `printStuff(@[lines])`, because `printStuff(lines)` would ""unwrap"" 
it and provide a list of unknown length; whereas either 
`printStuff(lines,lines)` or `printStuff(@[lines,lines])` would result in an 
argument list of 2 arguments, regardless of the length of lines.

This (apparent) inconsistency is the source of the confusion. Personally, I 
prefer the Python behaviour, but since we're past v1.0, I don't think it's 
worth discussing a breaking change even if everyone agrees with me (And not 
everyone does).


Re: Why does the this code work?

2020-02-18 Thread lscrd
There is no reason to use a special syntax to tell the compiler that expansion 
is needed. Thanks to static typing, the compiler is able to see if the array or 
sequence must be transmitted as a whole to the procedure or must be expanded.

In Python, you need a special syntax. Given a function _def f(*x)_ and a list 
_lst_ , if you write _f(lst)_ , _x_ will be a tuple whose first (and only) 
elements will be _lst_. You have to use the special syntax _f(*x)_ to transmit 
each element of _lst_ as an individual argument and, in this case, _x_ will 
contain the elements of _lst_ and not the whole list.

There is another case where the Nim compiler uses its knowledge of types to 
help the programmer: this is the automatic dereferencing of references and 
pointers. Given a _ref object_ , when accessing a field _a_ via a reference _p_ 
, you write _p.a_ and the compiler knows that it must dereference _p_. In C, 
you would have to write something like _(*p).a_ or _p- >a_.


Re: Why does the this code work?

2020-02-17 Thread cumulonimbus
The surprise (as I understand it, and I remember it surprised me too reading 
the docs) is the automatic expansion of the arguments. The consistent way would 
be for `printStuff(lines)` above to provide 1 argument of type seq[string], in 
the same way each arg of `printStuff(lines, lines)` would do. As it is, a 
single "lines" argument results in an arbitrary length x, but two arguments 
result in x.len==2.

e.g. in Python, you have the same functionality, but you have to prefix the arg 
with a `*` to say "I wish to expand this list into an argument list and not 
pass it as a single argument", which is consistent with the use of `*` in 
similar contexts, and with the passing of any other individual argument.


Re: Why does the this code work?

2020-02-16 Thread doofenstein
Besides the ability to apply function (like stringify `$`) to the parameters, 
varargs is nothing but an openArray with an alternative way of specifying 
arguments available. The normal way is still useful for e.g. when you forward 
parameters or when you don't know how many parameters you have and you pas over 
a seq:


import strutils

proc printStuff(x: varargs[string]) =
  for element in x:
echo element

let lines = readFile("file.txt").splitLines()

# the same proc used in two occaisons
# afaik in C++ you would have to write a wrapper for printStuff
printStuff "Hi, how are you going?", "Here's the content of a file"
printStuff lines


Run


Re: Why does the this code work?

2020-02-16 Thread dawkot
Varargs has to be the last parameter, openarray(s) can be anywhere.


Re: Why does the this code work?

2020-02-15 Thread Stefan_Salewski
Well, we may ask: Why do we have openArray proc parameter type at all, when 
varargs works for multiple arguments, for a seq and for an array? So varargs 
should be able to fully substitute openArray parameter type. Maybe varargs has 
more overhead, or maybe there exists cases where we want to allow passing an 
array or a seq, but not multiple individual parameters?


Re: Why does the this code work?

2020-02-15 Thread sigmapie8
But the code is for accepting multiple individual integers, not for accepting 
an array/sequence. It feels like the code isn't doing 'exactly' what it was 
intended to do. It's sort of doing more.


Re: Why does the this code work?

2020-02-15 Thread dawkot
Why shouldn't it 樂? The implicit conversion to a varargs/openarray (same thing) 
is cheap.


Why does the this code work?

2020-02-15 Thread sigmapie8

proc dispayVarargs(va: varargs[int]) =
echo va.len

var se: seq[int] = @[2, 3, 4]

dispayVarargs(se)


Run

I am happy that it works but it feels like breaking design.