Hacker News new | ask | show | jobs
by mmirate 2743 days ago
That ought to be a oneliner in any sane language today:

    numbers.into_iter().filter(|n| n>10 && n%2!=0).for_each(work);

    map work . filter ((/=0) . (`mod` 2)) . filter (>10) $ numbers
Insert tirade about how for-loops are free to do so much that they are slower-to-comprehend than specific-purpose iterator/list functions, here.
2 comments

The language is happy to accommodate any style you like best, including oneliners.

    sub work($n) { say $n }
    my @numbers = 1..100;

    # rubyish
    @numbers.grep(* > 10 && * %% 2).map(&work);

    # lol turbo haskal
    map &work <== grep * %% 2 <== grep * > 10 <== @numbers;

    # same, but in proper reading direction
    @numbers ==> grep * > 10 ==> grep * %% 2 ==> map &work;
The traditional function composition operator exists, see https://docs.perl6.org/routine/%E2%88%98
The following doesn't do what you think it does

    * > 10 && * %% 2
That is two WhateverCode objects which each take one argument. Since both are definite it gives you the second one.

    my &a = * > 10;
    my &b = * %% 2;

    my &c = &a && &b;

    &c === &b; # True
If it wasn't split up by the `&&`, it would be a code object that took two arguments.

    # using multiplication (×) as a boolean and
    # (it always cooperates in the WhateverCode lambda syntax)
    my &c = (* > 10) × (* %% 2);

    say so c(10,2); # True

    say (1..20).grep(&c);
    # ((11 12) (13 14) (15 16) (17 18) (19 20))
Note that `grep` is written in terms of `map`

    (1..20).map({ ($^a,$^b) if  ($^a > 10) × ($^b %% 2) })
    # ((11 12) (13 14) (15 16) (17 18) (19 20))
If you need to refer to an argument more than once, you (generally) can't do it with the WhateverCode lambda syntax.

    ->   $n {  $n > 10 &&  $n %% 2 }
            { $^n > 10 && $^n %% 2 }
    sub ($n){  $n > 10 &&  $n %% 2 }
I say generally because array indexing will give you the number of elements for all the arguments you ask for.

    @a[ (* × ⅓) .. (* × ⅔) ]
    @a[ (@a.elems × ⅓) .. (@a.elems × ⅔) ]
I noticed that error too but decided I didn't have the energy to provide a response worthy of the situation.

I'm so glad I didn't try. As always you've provided a helpful answer and I learned something new. I hadn't twigged that `[...]` context would treat each Whatever as the same value -- though in retrospect I can see of course it would given the Perlish principle of doing something very useful rather than doing something useless (generating an error).

I noticed what looked like a mistake in your post:

    my &c = (* > 10) × (* %% 2);

    say so c(10,2); # True
I thought "surely that returns False" and when I tried, it did.
Right it was late, and I was writing the code in different ways when writing here and writing in the REPL.
Here is a slight modification that takes advantage of the hyper operator >> (»):

  @numbers.grep(* > 10 && * % 2)>>.&work;
https://docs.perl6.org/language/operators#index-entry-hyper_...