The Special Little Symbol
Yesterday I showed you a FizzBuzz solution in YS. Here it is again:
!YS-v0
defn main(n=100):
each x (1 .. n): !:say
or? _ x:
str ((x % 3).! &&& 'Fizz'):
((x % 5).! &&& 'Buzz')
See that _
sitting there in the middle all by itself?
What's that all about?
Well _
is a special symbol in YS, and it means different things in different
contexts.
The _
Placeholder🔗
In that code we want the result of the str(...)
call, which will either be
Fizz
, Buzz
, FizzBuzz
or an empty string.
If it was an empty string then we want to use the value of x
.
Basically we wanted or?(str(...) x)
or put another way str(...) ||| x
.
In this case the str(...)
call was to big to fit on one line.
So we used _
to mean: put the big expression after the :
where the _
is.
This ends up being a really helpful when the first argument is a function and
you want to use a non-trivial anonymous function for it.
A common case for this is the reduce
function.
Here's a reduce
to find prime numbers:
!YS-v0
say:
reduce _ [2] (3 .. 100):
fn(primes number):
if primes.map(mod + number).some(zero?):
primes
conj(primes number)
Let's run it:
$ ys primes.ys
[2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
The reduce
function takes 3 arguments:
- A function to call for each element in the list
- An initial value
- A list to reduce
It would be nicer the the function came last because the 2nd and 3rd arguments are usually short.
If we had already defined the prime-finder
function we could have written:
reduce prime-finder [2] (3 .. 100)
.
But often the function is not reusable so we just want to write it inline.
The _
placeholder lets us get the best of both worlds.
The _
Dummy Variable🔗
In multi-variable assignments we can do this:
_ a b _ c =: a-list
Which could be written as:
a b c =: + [a-list.1, a-list.2, a-list.4]
Use _
as a dummy variable to ignore some of the values.
You could also use it in function arguments:
$ ys -e '
defn shift([_ *rest]): rest
say: (0 .. 4):shift'
(1 2 3 4)
Here we define a shift
function that uses _
to ignore the first argument
and return the rest.
The _
Position Indicator🔗
Most common functions used in chains, are "smart" about their arguments.
For example, these are all equivalent:
list.take(5)
5.take(list)
take(5 list)
The take
function takes a number and a list.
The .
chain operator puts the LHS into the first position.
That means that list.take(5)
should have been evaluated as take(list 5)
which is wrong and would throw an error.
But YS handles take
and other common functions specially and checks the
argument types at runtime and does the right thing for you.
Unforunately, this is not true for all functions, and also the runtime check takes some time.
You can also write that as: list.take(5 _)
.
The _
indicates the position to put the LHS into.
It also disables the "smart" runtime check since you told it explicitly where
things should go.
This makes it a little faster to run, which might be important sometimes.
If you wrote your own foo-bar
function that also took a number and a list,
you'd need to use _
for list.foo-bar(5 _)
because foo-bar
wouldn't have
the special "smart" property.
Using _
in Anonymous Functions🔗
We've already seen this but _
is the shorthand for the first argument in an
anonymous function.
$ ys -e '
squared =: \(_ * _)
say: 8:squared
'
64
The Previous Document Value🔗
In a multi-document YAML file, the _
symbol is the previous document value.
$ ys -e '!YS-v0
--- !data
foo: blue
bar: 10
--- !code
say: _.foo * _.bar
'
blueblueblueblueblueblueblueblueblueblue
You can use this for one liners that take a file and also a -e
expression
argument:
$ curl -sL https://gist.github.com/gsscoder/e0e905fbef23376aabfa695d85d8ef5c/raw |
ys -e 'say: rand-nth(_)' -
Finnegan
https://gist.github.com/gsscoder/e0e905fbef23376aabfa695d85d8ef5c
is a JSON
(aka YAML) file with a sequence of first names; posted as a GitHub Gist.
Since YS always evaluates the -e
expression after the file (-
for stdin
here) is evaluated, _
is the value of the evaluated file.
I hope I remembered all of the places you can use _
in YS.
It's quite possible that YS will have more places to use _
in the future.
If you have ideas for more places to use _
in YS, please let me know in the
comments.