[PYTHON] About Nim higher-order functions for Nim beginners written by Nim beginners

What to write in this article

In this article, I will introduce the higher-order function provided by Nim and compare it with Python. It also includes tips on how to write Nim.

What is Nim?

*** Efficient, expressive and elegant Nim is a statically typed compiled system programming language. It combines the successful concepts of mature languages such as Python, Ada, and Modula. *** *** (Quote: https://nim-lang.org/ with Google Translate) In short, it has a syntax like Python and is a programming language as fast as C language. It's a dream language for me, who usually writes Python but is dissatisfied with its speed.

What is a higher-order function?

A higher-order function is a function *** that takes a *** function as an argument. It was used in LISP and ML languages in the old days, but it has been implemented in many programming languages due to the rise of functional languages in recent years. For example, it has been implemented in scripting languages such as Python, and more recently in JavaScript (since ECMAScript 2015). It seems that it can be written in Rust and Go, but I am not familiar with it so I will omit it.

Nim higher-order functions

Introducing higher-order functions and their templates implemented in Nim's sequtil module.

map

map


proc map[T, S](s:openArray[T];op:proc(x:T):S{...}): seq[S] {...}

map takes an array s of type ʻopenArray and a procedure ʻop as arguments, and returns seq with ʻop applied to each element of s. ʻOpenArray is a general-purpose type that indicates an array, and includes sequences, string, and ʻarray`.

map example


import sequtils

let #This is an immutable variable declaration
  s = [1,2,3,4] #This is an Array type
  op = proc (x: int): int = x * x #Anonymous function, a function that returns the square of an argument

echo s.map(op) # => @[1, 4, 9, 16] ##Each element of s is squared
echo s # => [1, 2, 3, 4] ##The original array does not change
echo s.map(op) == map(s, op) # => true
##Nim Tips (How to call a procedure)
## p(x)And x.p()Is equivalent

apply

apply


proc apply[T](s:varopenArray[T];op:proc(x:T):T{...}) {...}

ʻApply takes an array s of type ʻopenArray and a procedure ʻop as arguments, and applies ʻop to each element of s. Similar to map, but ʻapply has no return value and modifies s` directly. Actually, there is another apply, but omitted.

apply example


import sugar #Experimental module
var #mutable variable declaration
  x = [true, false, false, true, true]
echo x #=> [true, false, false, true, true]

apply(x, b => not b) #Take not of each element of x
echo x #=> [false, true, true, false, false]
##Nim Tips (How to write anonymous functions)
## b =>not b is an abbreviation for anonymous functions. The left side is the argument and the right side is the return value
##However, import sugar is required

filter

filter


proc filter[T](s:openArray[T];pred:proc(x:T):bool{...}): seq[T] {...}

filter takes an array s of type ʻopenArray and a procedure predas arguments, and returnsseq consisting of elements of swherepred returns true`.

filter example


import strutils

let
  str = "happY holidAYs"
  upperStr = str.filter(s => s.isUpperAscii()) #Filter uppercase

echo str #=> "happY holidAYs"
echo upperStr #=> @['Y', 'A', 'Y']
echo upperStr.join("") #=> "YAY" ##Combine elements of a string type array(Same as Python)
##Nim Tips (naming)
##It is recommended to declare Nim variables and procedures in camelCase.

keepIf

keepIf


proc keepIf[T](s:varseq[T];pred:proc(x:T):bool{...}) {...}

keepIf takes s of type seq and procedure pred as arguments, and leaves only the elements that pred returns true in s. However, note that the argument is seq instead of ʻopenArray`.

Useful templates (mapIt, applyIt, filterIt, keepItIf)

These are the map, apply, filter and keepIf templates, respectively. With these, you can easily (just a little) call higher-order functions. Since the usage is almost the same, I will introduce an example of mapIt.

mapIt example


let 
  v = [1,2,3,4,5]
  w = v.mapIt(it*2) #it means each element of v, which means to double each element
echo w # => @[2, 4, 6, 8, 10]

point --The arguments of mapIt (and so on) are arrays and ** expressions ** --ʻItin the template is each element of the array of arguments --The return value isseq` like the original function

Comparison with Python

Python also implements map, filter, reduce (corresponding to foldl, foldr), but there is no equivalent to apply or keepIf (pandas has it). Therefore, if you want to use the list after multiplying the list l by map,

l = [1, 2, 3, 4] #I want to double each value
mapped_l = map(lambda x: x*2, l) # mapped_l is not a list
assert type(mapped_l) is map # => true
mapped_l = list(mapped_l) #Return to list

Must be. The return type of map is map object, which is different from the argument. This is a generator, so if you want to use it as the original type, you have to explicitly return it. This is the same for filter, and the return value of filter is filter object. For example

l = [-3, -2, -1, 0, 1, 2, 3] 
p = filter(lambda x: x>0, l) #Leave only positive elements
len(p) #Error because p is a filter object
len(list(p)) #This is okay. The answer is 3
len([li for li in l if li > 0]) #This is also okay. Is this a Python-like way of writing? ?? ??

I personally don't like this very much. In the case of Nim, the return type of l.map (proc ...) is seq, so it is easy to use because there is no need for such processing (personal impression).

in conclusion

I summarized the higher-order functions of Nim. Nim is still a developing language, but I hope it will develop further in the future. I hope it helps you a little: upside_down:

Recommended Posts

About Nim higher-order functions for Nim beginners written by Nim beginners
Python for super beginners Python #functions 1
Django tutorial summary for beginners by beginners ③ (View)
Django tutorial summary for beginners by beginners ⑤ (test)
A textbook for beginners made by Python beginners
Django tutorial summary for beginners by beginners ⑦ (Customize Admin)
An introduction to object-oriented programming for beginners by beginners
Django tutorial summary for beginners by beginners ⑥ (static file)
Django Tutorial Summary for Beginners by Beginners (Model, Admin)
Django tutorial summary for beginners by beginners ① (project creation ~)
Django tutorial summary for beginners by beginners ④ (Generic View)
About Python external module import <For super beginners>
Roadmap for beginners
About Go functions
[Linux] Basics of authority setting by chmod for beginners
Learn about python's print function and strings for beginners.