Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass an operator like a function

Tags:

While learning Raku, I arrive to the point of higher order function and the sort function.

I have this example:

> sort <4 6 2 9 1 5 11> (1 2 4 5 6 9 11) 

Then the doc for the routine says this:

Sorts the list, smallest element first. By default infix:<cmp>  is used for comparing list elements. 

And the book that I'm following "Piensa en raku", in section 9.2, makes a comparative between numeric sort and lexicographic sort.

I tried the following:

> sort &le, <4 6 2 9 1 5 11>; ===SORRY!=== Error while compiling: Undeclared routine:     le used at line 1. Did you mean 'lc'? 

But getting this problem, instead of the sorted list lexicographically ordered. So may be is too early for me to understand this, but should be possible to pass an operator in Raku like a function, since also the documentation says that it is using an infix: or I need to do something like this, maybe I'm confusing operators and subroutines:

sub my-le($a,$b) {     $a le $b; }  sort &my-le, <4 6 2 9 1 5 11>; 

or this:

   sort { $^b le $^a  }, <4 6 2 9 1 5 11>; 

So I have the question about different use the infix operator and a subroutine, maybe the problem about this difference is that the order of the operands affect the result of some operations. so you can not use so lightly passing it as a function or a parameter or variable

> sort { $^a le $^b  }, <4 6 2 9 1 5 11> (9 6 5 4 2 11 1) > sort { $^b le $^a  }, <4 6 2 9 1 5 11> (1 11 2 4 5 6 9) 

I hope that I can explained my doubts on this problem.

like image 490
anquegi Avatar asked Oct 13 '20 09:10

anquegi


People also ask

Can I pass an operator as a parameter?

I'd pass it as a string, then determine the passed string in the function and e.g use a switch construct to do the corresponding operation. Operators can't be passed like that, and they can't generally be substited by variables, so operators suck that way.

Can we pass a function as an argument to a function?

We cannot pass the function as an argument to another function. But we can pass the reference of a function as a parameter by using a function pointer. This process is known as call by reference as the function parameter is passed as a pointer that holds the address of arguments.

Can we pass an expression to a function?

Short answer: You can't. The result of the expression evaluation is passed to the function rather than the expression itself.


Video Answer


2 Answers

The le operator is defined something like this :

sub infix:<le> { ... } 

The infix: prefix tells the language it's a infix operator. So if you want to call is as a sub its &infix:<le>(1,2) or for your sort :

sort &infix:<le>, <4 6 2 9 1 5 11>; (9 6 5 4 2 11 1) 

This may help https://docs.raku.org/language/optut

like image 143
Scimon Proctor Avatar answered Sep 28 '22 08:09

Scimon Proctor


Adding to Scimon's answer and in case you want a more "clear" presentation, you can use the following whatever construct:

sort *le*, <4 6 2 9 1 5 11>; 

The previous code is a whatever construct (code object).

The whatever construct uses multiple * to generate blocks of code (anonymous subroutines) with as many arguments:

my $c = * + *;   # same as   -> $a, $b { $a + $b } 

This means that the whatever sign (*) is used to denote the two (ore more) parameters that are used in the calculation

The same goes for our case:

sort *le*, <4 6 2 9 1 5 11>; 

is the same as :

sort * le *, <4 6 2 9 1 5 11>;   # adding space between operator and the whatever sign (*) 

and this by turn is the same as :

sort -> $a, $b { $a le $b }, <4 6 2 9 1 5 11>;   # anonymous subroutine   

or

sort { $^a le $^b }, <4 6 2 9 1 5 11>; 

or even

sub le {     $^a le $^b }  sort &le, <4 6 2 9 1 5 11>; 

References:

https://docs.raku.org/type/Whatever

https://docs.raku.org/type/Block

like image 43
jakar Avatar answered Sep 28 '22 07:09

jakar