for i in 0..10: echo "Hello World"[0..i]
community/nim
). Save this code in the file hello.nim, compile it with nim c hello.nim
, and finally run the executable file ./hello
. Or use the nim -rc hello.nim
, which will compile and run the resulting file. To build an optimized version, use the nim -d:release c hello.nim
. After launching, you will see this output in the console:
H He Hel Hell Hello Hello Hello W Hello Wo Hello Wor Hello Worl Hello World
import unsigned, strutils type CRC32* = uint32 const initCRC32* = CRC32(-1) proc createCRCTable(): array[256, CRC32] = for i in 0..255: var rem = CRC32(i) for j in 0..7: if (rem and 1) > 0: rem = (rem shr 1) xor CRC32(0xedb88320) else: rem = rem shr 1 result[i] = rem # Table created at runtime var crc32table = createCRCTable() proc crc32(s): CRC32 = result = initCRC32 for c in s: result = (result shr 8) xor crc32table[(result and 0xff) xor ord(c)] result = not result # String conversion proc $, automatically called by echo proc `$`(c: CRC32): string = int64(c).toHex(8) echo crc32("The quick brown fox jumps over the lazy dog")
414FA339
. However, it would be much better if we could calculate the CRC table at compile time. And in Nim this can be done very easily, we replace our string with assignment of crc32table to the following code:
# Table created at compile time const crc32table = createCRCTable()
var
with const
. Great, isn't it? We can write the same code that can be executed both in the work of the program and at the compilation stage. No template metaprogramming.
template times(x: expr, y: stmt): stmt = for i in 1..x: y 10.times: echo "Hello World"
times
to a normal loop:
for i in 1..10: echo "Hello World"
10.times
syntax, then know that this is just a normal call to times
with the first argument 10
and a block of code as the second argument. You could just write: times(10):
see more about Unified Call Syntax below.
template newSeqWith(len: int, init: expr): expr = var result = newSeq[type(init)](len) for i in 0 .. <len: result[i] = init result # Create a 2-dimensional sequence of size 20,10 var seq2D = newSeqWith(20, newSeq[bool](10)) import math randomize() # Create a sequence of 20 random integers smaller than 10 var seqRand = newSeqWith(20, random(10)) echo seqRand
var res: seq[int] = @[] for x in 1..10: if x mod 2 == 0: res.add(x) echo res const n = 20 var result: seq[tuple[a,b,c: int]] = @[] for x in 1..n: for y in x..n: for z in y..n: if x*x + y*y == z*z: result.add((x,y,z)) echo result
future
module and write:
import future echo lc[x | (x <- 1..10, x mod 2 == 0), int] const n = 20 echo lc[(x,y,z) | (x <- 1..n, y <- x..n, z <- y..n, x*x + y*y == z*z), tuple[a,b,c: int]]
var x: int for i in 1..1_000_000_000: x += 2 * i echo x
template optMul{`*`(a,2)}(a: int): int = let x = a x + x template canonMul{`*`(a,b)}(a: int{lit}, b: int): int = b * a
a * 2
can be replaced by a + a
. In the second pattern, we indicate that the int
variables can be swapped, if the first argument is a constant number, this is necessary so that we can apply the first pattern.
template optLog1{a and a}(a): auto = a template optLog2{a and (b or (not b))}(a,b): auto = a template optLog3{a and not a}(a: int): auto = 0 var x = 12 s = x and x # Hint: optLog1(x) --> 'x' [Pattern] r = (x and x) and ((s or s) or (not (s or s))) # Hint: optLog2(x and x, s or s) --> 'x and x' [Pattern] # Hint: optLog1(x) --> 'x' [Pattern] q = (s and not x) and not (s and not x) # Hint: optLog3(s and not x) --> '0' [Pattern]
s
optimized to x
, r
also optimized to x
, and q
immediately initialized to zero.
bigint
, take a look at templates that start with opt
in the biginsts.nim library :
import bigints var i = 0.initBigInt while true: i += 1 echo i
proc printf(formatstr: cstring) {.header: "<stdio.h>", varargs.} printf("%s %d\n", "foo", 5)
void hi(char* name) { printf("awesome %s\n", name); }
{.compile: "hi.c".} proc hi*(name: cstring) {.importc.} hi "from Nim"
proc set_default_dpi*(dpi: cdouble) {.cdecl, importc: "rsvg_set_default_dpi", dynlib: "librsvg-2.so".}
gcDisable() while true: gameLogic() renderFrame() gcStep(us = leftTime) sleep(restTime)
type FakeTune = enum freeze, solo, noJump, noColl, noHook, jetpack var x: set[FakeTune] x.incl freeze x.incl solo x.excl solo echo x + {noColl, noHook} if freeze in x: echo "Here be freeze" var y = {solo, noHook} y.incl 0 # Error: type mismatch
var a: array[FakeTune, int] a[freeze] = 100 echo a[freeze]
len
and append
functions or methods. In Nim, you don't need to remember this, because you can write as you please. Nim uses Unified Call Syntax (Unified Call syntax), which is also now proposed in C ++ by the comrades Herb Sutter and Bjarne Stroustrup.
var xs = @[1,2,3] # Procedure call syntax add(xs, 4_000_000) echo len(xs) # Method call syntax xs.add(0b0101_0000_0000) echo xs.len() # Command invocation syntax xs.add 0x06_FF_FF_FF echo xs.len
import htmlgen, dom type Data = object visitors {.importc.}: int uniques {.importc.}: int ip {.importc.}: cstring proc printInfo(data: Data) {.exportc.} = var infoDiv = document.getElementById("info") infoDiv.innerHTML = p("You're visitor number ", $data.visitors, ", unique visitor number ", $data.uniques, " today. Your IP is ", $data.ip, ".")
Data
that will be sent from the server to the client. The procedure printInfo
will be called with this data for display. To build our client code, run the nim js client
command. The result will be saved in nimcache/client.js
.
nimble install jester
. Now we write our server.nim:
import jester, asyncdispatch, json, strutils, times, sets, htmlgen, strtabs var visitors = 0 uniques = initSet[string]() time: TimeInfo routes: get "/": resp body( `div`(id="info"), script(src="/client.js", `type`="text/javascript"), script(src="/visitors", `type`="text/javascript")) get "/client.js": const result = staticExec "nim -d:release js client" const clientJS = staticRead "nimcache/client.js" resp clientJS get "/visitors": let newTime = getTime().getLocalTime if newTime.monthDay != time.monthDay: visitors = 0 init uniques time = newTime inc visitors let ip = if request.headers.hasKey "X-Forwarded-For": request.headers["X-Forwarded-For"] else: request.ip uniques.incl ip let json = %{"visitors": %visitors, "uniques": %uniques.len, "ip": %ip} resp "printInfo($#)".format(json) runForever()
/client.js
and /visitors
connected. /client.js
will return the file received through the nim js client
, and /visitors
will generate the JS code with a call to printInfo(JSON)
.
You're visitor number 11, unique visitor number 11 today. Your IP is 134.90.126.175.
Source: https://habr.com/ru/post/258119/