• Subject: Re: Unpack Operator
• From: Benoît de Chezelles <benoit.dechezelles@...>
• Date: Sat, 10 Feb 2018 12:13:02 -0800

2018-02-10 10:49 GMT-08:00 Paige DePol <lual@serfnet.org>:
> So this splat and double splat are essentially unpack operators, which
> was the original title and discussion topic of this thread. Nice!
Hehe, maybe we're going somewhere after all with all of this!

Next we'll need to find a way to apply all or part of this to Lua.

>> #-----------------------
>> def foo(x, y, z, a = 1, b = 2, c = 3)
>>  puts "#{x}, #{y}, #{z}, #{a}, #{b}, #{c}"
>> end
>>
>> foo 1, 2, 3, 4, 5, 6
>
> Okay, my reading of the documentation last night lead me to believe there
> should be an error that there was no named argument 'a', so how is 4, 5, 6
> being assigned to a, b, c in this example?
>
> Oh wait, it's because in this case a, b, c aren't named parameters they are
> just positional ones with default values. I see. My bad. Sigh!
>
> So then that does make sense, sorry Sean, I totally was thinking that a, b,
> c were named arguments not positional parameters in these specific examples.
> As there is no way to easily determine where positional and named parameters
> start and stop that is why they use a solo 'splat' marker.

Yes exactly, and also positional arguments can be called as named arguments
too (detailed below).

>> foo x: 1, y: 2, z: 3, a: 4, b: 5, c: 6
>> foo *{1, 2, 3, 4, 5, 6}
>> foo **{x: 5, y: 6, z: 7}
>
> So in Crystal you can create tuples using the same syntax we use
> for tables in Lua then? Good to know, guess I should have clicked
> on the links for Tuple and NamedTuple!
>
> And in these cases the
> created tuple is just being created and unpacked... that doesn't
> seem the most terribly efficient method for passing arguments.

Sure, in this case the use of (named)tuple is completely useless, but
when you have
a (named)tuple coming from outside (the caller, generated from a json
string, ..), it
starts to be useful!

About the efficiency, I'll going a bit out of topic here, and I'm not
sure I'll explain it clearly enough..

Basically in Crystal, Tuple & NamedTuple are a compile-time immutable construct,
allocated on the stack (the real stack, there is no VM or bytecode or
anything), as all
the types are known at compile time, the compiler can pass the correct
values from
the (Named)Tuple, or the default values, or positional/named values
at the correct places on the stack so the method body can find them
and use them.

It's not a dynamic data structure that you create then unpack, they
are just a virtual
concept to powerfully manipulate a set of values on the stack (not
sure it even mean
something..), so there is very little to no overhead to use them to
pass args in Crystal.

Quoting a question from above:
> So the "splat" qualifier is actually an operator as well? I missed the
> line that sort of intimated at this possibility and thought that the
> symbol was a variable qualifier for function parameters only.

It's not really an operator, well, it is but it works only on Tuple
(for *) and NamedTuple (for **).

>
>
>> puts "You could mix things up"
>>
>> (live at https://carc.in/#/r/3jwq)
>
> Thanks for the live example, that helped to clarify things. The
> previous post of mine would have all made sense were the a, b ,c
> arguments named and not positional... I still like the syntax
> though having to have a solo splat on all functions without any
> positional arguments is a bit of a wart.
>
> Obviously, I missed the importance of the solo splat as a way
> to separate the two styles of parameters. Because a, b, c had
> default parameters I was thinking they were named parameters.

The solo splat in Crystal is only used to force the user to call the
next arguments using
named parameter, but all params are always callable with its name:

def foo(x, y, *, z = 3)
end

# these calls will always give x = 1, y = 2, z = 3

# normal positional
foo 1, 2

# named positional
foo x: 1, y: 2

# cannot use non-named z arg
foo 1, 2, 3 # => Error

# use named z arg
foo 1, z: 3, 2

# mixing
foo y: 2, 1, z: 3

> Again, Sean, sorry... I had just misunderstood the syntax s
> your examples were correct and my clarifications were not! :(

I'd say "don't be sorry", reading the documentation of a new language
which have different
paradigms and expect to understand everything is a no-no! It's normal
to be confused here I
think, even though one know another language (Lua) very well :)