nixfreak

Learning Nim programming language

Learning Nim

I have been using nim-lang or nim off and on for about 6 mo. I really like the language and its fun to program in , but I have no patience to actually learn nim the correct way. I mean instead of just throwing shit together and thinking (I am cool). So I bought the books Nim In Action and Mastering Nim and I am going to go through both the books to understand better about programming.

This blog platform supports markdown language so I should be able to use code injection . Great it works now I can write code examples. I usually use Joplin App for all my notes but I decided to actually post this online for others to see.


For those whom have never heard of the Nim language take a look and see for yourself. Its very easy to get started and learn.


Nim In Action:

Starting Mastering Nim:

Example's will be from both books

[WARNING] you need to install libsdl or SDL and Fira-sans.ttf font. On Archlinux based distros you can install via.

sudo pacman -S sdl ttf-fira-sans

Drawing Horizontal and Vertical lines

import pixels

type
  Point = object
     x: int
     y: int

var p = Point(x: 5, y: 7)

putPixel(p.x, p.y)

Now we want to run the command on a terminal or command line like this:

nim c pixel1.ex

So lets talk about this example. import pixels is nim's way of importing a library, Type is for static types , one of the many reason's why Nim is such a powerful and flexible language. We create a type called Point and we make Point an object. The Point object has x and y which are both integers. We then want to create a variable to that is in instance or Point called p , p will hold our coordinates of x and y. We call putPixel with p.x and p.y,

[IMG1 - output of compiled nim program]

shot-2022-11-20_13-27-36.jpg

It doesn't look like much but shows us that we have a point using x, y plain.

This next example will actually show us how to draw a horizontal and vertical line


import pixels

  type
    x: int
    y: int

# Create a proc to draw a horizontal line
proc drawHorizontalLine(start: Point, length: Positive) =
  for delta in 0 .. length:
     putPixel(start.x + delta, start.y)

# Create a proc to draw a vertical line
proc drawVerticalLine(start: Point, length: Positive) =
  for delta in 0 .. length:
    putPixel(start.x, start.y + delta)


# crate a point with coordinates x: 60, y: 40
let a = Point(x: 60, y: 40)

# call the two procs (drawHorizontalLine and drawVerticalLine)

drawHorizontalLine(a, 50)
drawVerticalLine(a, 30)

nim c pixel2.nim

[IMG2 - output of compiled nim program] shot-2022-11-20_13-12-00.jpg

So we can see from the image you have two points a horizontal and vertical one using x and y plain. Those points then show up graphically on the screen.

So how does this work? Let's break this program down list style.

  • import the pixels library (import pixels)

  • create a type called Point and create and x and y integer

  • create a proc or (procedure) called drawHorizontalLIne

    • using a starting Point object as a starting point and using length as a Positive integer only.
    • create a for loop of the delta (This actually could be any variable name)
    • and iterate or loop through 0 - length (remember length is a positive integer so it would be for x in 0 through and up to the positive number.
  • create a proc or (procedure) called drawVerticalLine
    • using a starting Point object as a starting point and using lenght as a Positive integer only.
    • create a for loop of the delta (This actually could be any variable name)
    • and iterate or loop through 0 - length (remember length is a positive integer so it would be for x in 0 through and up to the positive number.
  • Create a variable called "a" and assign it to Point then use x and y to create points i.e. x: 60 , y: 40.
    • call the two procs to draw the horizontal and vertical lines.
    • and use a as a parameter and the "Positive" number.

We can even extend this example


import pixels

  type
    x: int
    y: int

  type
    Direction = enum
      Horizontal
      Vertical


# Create a proc to draw a horizontal line
proc drawHorizontalLine(start: Point, length: Positive) =
  for delta in 0 .. length:
     putPixel(start.x + delta, start.y)

# Create a proc to draw a vertical line
proc drawVerticalLine(start: Point, length: Positive) =
  for delta in 0 .. length:
    putPixel(start.x, start.y + delta)


# Create a proc that will combine both drawHorizontal and drawVertical
proc drawLine(start: Point, length: Positive, direction: Direction) =
  case direction
  of Horizontal:
    drawHorizontalLine(start, length)
  of Vertical:
     drawVerticalLine(start, length)

# crate a point with coordinates x: 60, y: 40
let a = Point(x: 60, y: 40)

#  Call drawLine
drawLine(a, 50, Horizontal)
drawLine(a, 30, Vertical)

[IMG3 - output of compiled nim program] shot-2022-11-20_13-12-00.jpg

Our image hasn't changed , it now just easier to call one procedure instead of many

So we have extended our pixel program so that we don't have to call drawHorizontal and drawVertical over and over to create lines. We can combine both of them with a new procedure.

There are a couple of new terms we are using here: - enum: which stands for enumeration - case: which is nim's switch statement

Enum

type
  Colors = enum 
     blue, red, green

var b = Colors.blue
echo b (answ: blue)

echo Color.blue

enumerated type defines a collection of identifiers have some some type of meaning attached to them.

Case

case myVar
 of "pet1", "pet2", "pet3":
    echo "Great pet"
 else:
    echo "Misunderstood pet"

case which is nim's "Switch statement".


Rendering Text

The pixels library is very simple but it does support text rendering. [WARNING] you need to install Mozilla's Fira-sans.ttf font otherwise this won't render to the SDL canvas

import pixels

drawText 100, 30, "You should be on Mastodon", 34, Blue

[IMG3] Render Text shot-2022-11-20_21-31-47.jpg


Nim variables

There are 3 types of keywords that nim uses for storage variables:

  • const - Immutable value and executed at compile time
  • var - Mutable value (The value can be changed)
  • let - Immutable value (The value cannot be changed)

Install inim

inim is a program written in nim and is a REPL (Read-Eval-Print Loop). This allows us to practice on a terminal / command line

nim> const PI = 3.14159
nim> var pi: float
nim> pi = 3.14159
nim> let pi = 3.14159
Error: redefinition of 'pi'; previous declaration here: /tmp/inim_1669002625.nim(20, 5)
the variable "pi" is already assigned.

nim> PI
3.14159 == type float64
nim> pi
3.14159 == type float
nim> let thisPI = 3.14159 # We assign "thisPI" to 3.14159
nim> thisPi
3.14159 == type float64
nim> thisPI
3.14159 == type float64

Let's use inim to print out (var, let and const)

nim> var a = 10
nim> let b = 20
nim> const c = 100

Lets print out the result on one line.

nim> echo "var a = ", $a & " ",  "var b = ", $b & " " , "var c = ", $c
var a = 10 var b = 20 var c = 100

The "&" is to concatenate and " " is for spaces.

Find the index of a string starting at 0

proc find(haystack: string; needle: char): int =
  for i in 0 ..< haystack.len: # this will always be true (if i is less than the string.len)
                               # meaning a string is counted starting at 1 .. n , and an index
                               # starts at 0 , so therefore 0 is the start but string starts at 1
                               # so this will always be true
    if haystack[i] == needle: return i # if the string[index i which starts at 0] is equal to the needle
                                       # which is our "char" character ' ' then return the index of i
                                       # which if we had "abcdefghi" for our haystack string and we choose
                                       # 'g' then the index of g - -remember starting with 0 is 6
                                       # let try
  return -1


let index = find("l;kasdf", 's')
echo index

echo "l;kasdf".len

Here is our results:

nim c -r --verbosity\:0 --hint\[Processing\]\:off --excessiveStackTrace\:on /home/nixfreak/lang/nim/practice/mn/hackstack.nim
4
7
The index of 'g' is: 6

Find the length of the string abcdefghi
7


Nixfreak public key

nixfreak dot protonmail.ch

Fingerprint: B19B C26C 80AE 32D2 46C6 FBF1 AA2F 0EBC D327 6BF1

nixfreak_pub.png