Last active
August 29, 2015 14:24
-
-
Save dgellow/7bb55a392215a45997b6 to your computer and use it in GitHub Desktop.
Some fun with Nim. Based on http://learnxinyminutes.com/docs/nim/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import strutils as str | |
import math except sin | |
# Helpers | |
proc newline(text: string): string = | |
text & "\r\n" | |
proc colorize(text: string, color: int, isBright: bool): string = | |
let | |
boldVal: int = if isBright: 1 | |
else: 0 | |
"\e[$1;$2m$3\e[0m" % [boldVal.intToStr, color.intToStr, text] | |
proc writecolor(text: string, color: int, bright = false): void = | |
write(stdout, colorize(text, color, bright)) | |
proc echocolor(text: string, color: int, bright = false): void = | |
write(stdout, newline(colorize(text, color, bright))) | |
proc echoTitle(title: string): void = | |
let | |
decoration = "—".repeat(len(title)) | |
color = 30 | |
isBright = true | |
discard map(@[decoration, title, decoration], | |
proc (x: string): string = | |
echocolor x, color, isBright) | |
# Introduction | |
var | |
letter: char = 'n' | |
lang = "N" & "im" | |
nLength: int = len lang | |
boat: float | |
truth: bool = false | |
let | |
legs = 400 | |
arms = 2_000 | |
aboutPi = 3.141592653589 | |
const | |
debug = true | |
compileBadCode = false | |
when compileBadCode: | |
legs = legs + 1 | |
const input = readline(stdin) | |
discard 1 > 2 | |
discard map([1, 2, 3], proc (x: int): string = "Num:" & intToStr(x)) | |
# | |
# Data Structures | |
# | |
# Tuples | |
echoTitle "Tuples" | |
var | |
child: tuple[name: string, age: int] | |
today: tuple[sun: string, temp: float] | |
child = (name: "Sam", age: 23) | |
today.sun = "Overcast" | |
today.temp = 34 | |
echo child | |
echo today | |
# Sequences | |
var | |
drinks: seq[string] | |
drinks = @["Water", "Juice", "Chocolate"] | |
# | |
# Defining types | |
# | |
type | |
Name = string # type alias | |
Age = int | |
Person = tuple[name: Name, age: Age] # define data structures | |
AnotherSyntax = tuple | |
fieldOne: string | |
secondField: int | |
var | |
john: Person = (name: "John B.", age: 17) | |
newage: int = 18 | |
john.age = newage # it works since Age and int are synonyms | |
type | |
# 'distinct' makes a new type incompatible with its | |
# base type. | |
Cash = distinct int | |
Desc = distinct string | |
var | |
money: Cash = 100.Cash | |
description: Desc = "Interesting".Desc | |
when compileBadCode: | |
john.age = money # Error! age is of type int and money is Cash | |
john.name = description # Error too | |
# | |
# More types and data structures | |
# | |
# Enum | |
echoTitle "Enum" | |
type | |
Color = enum cRed, cBlue, cGreen | |
Direction = enum | |
dNorth | |
dWest | |
dEast | |
dSouth | |
var | |
# 'orientation' is of type Direction, value is 'dNorth' | |
orientation = dNorth | |
# 'pixel' is of type Color, value is 'cGreen' | |
pixel = cGreen | |
echo "Is North bigger than East?" | |
echo dNorth > dEast | |
echo "Is North smaller than East?" | |
echo dNorth < dEast | |
type | |
# Only an int from 1 to 20 is a valid value | |
DieFaces = range[1..20] | |
var | |
my_roll: DieFaces = 13 | |
when compileBadCode: | |
my_roll = 23 | |
# Arrays | |
echoTitle "Arrays" | |
type | |
# Arrays are fixed length and indexed by an ordinal type | |
RollCounter = array[DieFaces, int] # array length = length of DieFaces | |
DirectionNames = array[Direction, string] | |
Truths = array[42..44, bool] | |
var | |
counter: RollCounter | |
directions: DirectionNames | |
possible: Truths | |
possible = [false, false, false] | |
possible[42] = true | |
when compileBadCode: | |
possible[41] = true # Error: index out of bounds | |
directions[dNorth] = "The great white north" | |
directions[dWest] = "Don't go there! I saw a giant spider last night!" | |
my_roll = 13 | |
echo "Counter dice roll: " & counter[my_roll].intToStr | |
counter[my_roll] += 1 | |
echo "Counter dice roll: " & counter[my_roll].intToStr | |
counter[my_roll] += 1 | |
echo "Counter dice roll: " & counter[my_roll].intToStr | |
var anotherArray = ["Default index", "starts at", "0"] | |
# | |
# IO and Control Flow | |
# | |
# 'case', 'readLine()' | |
echoTitle "'case', 'readLine()'" | |
echo "Read any good books lately? [y/n]" | |
case readLine(stdin).toLower | |
of "n", "no": | |
echo "You should go to your local library." | |
of "y", "yes": | |
echo "Carry on, then!" | |
else: | |
echo "Uggh? Not sure to understand, but I assume that's great?" | |
# 'while', 'if', 'continue', 'break' | |
echoTitle "'while', 'if', 'continue', 'break'" | |
echo "I'm thinking of a number between 0 and 50. Guess which one!" | |
randomize() | |
let | |
number_to_guess: int = toInt(random(49.0) + 1) | |
var | |
raw_guess: string | |
guess: int | |
while guess != number_to_guess: | |
raw_guess = readLine(stdin) | |
if raw_guess == "": continue | |
guess = parseFloat(raw_guess).toInt | |
echo "toGuess: " & number_to_guess.intToStr | |
echo "guess: " & guess.intToStr | |
if guess > number_to_guess: | |
echo("Nope. Too high. You lose.") | |
break; | |
elif guess < number_to_guess: | |
echo("Your guess is too low.") | |
else: | |
echo("Good game, you found it.") | |
# | |
# Iteration | |
# | |
echoTitle "Iteration" | |
for i, elem in ["Yes", "No", "Maybe so"]: | |
echo(elem, " is at index:", i) | |
for pers, power in items(@[(person: "You", power: 100), | |
(person: "Me", power: 9000)]): | |
echo "Person: " & pers | |
echo "Power: " & power.intToStr | |
# Multiline raw string | |
echoTitle "Multiline" | |
let myString = """ | |
an <example> | |
`string` to | |
play with | |
""" | |
for line in splitLines(myString): | |
echo line | |
for i, c in myString: | |
if i mod 2 == 0: continue | |
elif c == 'X': break | |
else: echo c | |
# | |
# Procedures | |
# | |
echoTitle("Procedures") | |
type | |
Answer = enum aYes, aNo | |
proc ask(question: string): Answer = | |
echo question, " [y/n]" | |
while true: | |
case readLine(stdin).toLower | |
of "y", "yes": | |
return Answer.aYes | |
of "n", "no": | |
return Answer.aNo | |
else: echo "Please be clear: yes or no" | |
proc addSugar(amount: int = 2) = | |
assert(amount > 0 or amount < 9000, "Crazy Sugar") | |
for a in 1..amount: | |
echo a, " sugar..." | |
case ask("Would you like sugar in your tea?") | |
of aYes: | |
addSugar(3) | |
of aNo: | |
echo "Oh ... do take a little!" | |
addSugar() | |
# | |
# FFI | |
# | |
echoTitle "FFI" | |
proc sin(angle: float): float {.importc: "sin", nodecl.} | |
echo "Some sinus values:" | |
for angle in @[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]: | |
echo "angle: " & $angle & " rad | sin(angle): " & $sin(angle) | |
# | |
# Higher Order functions | |
# | |
echoTitle "Higher order functions" | |
proc first(s: seq, sortfn: proc, mapfn: proc): auto = | |
s.sorted(sortfn).map(mapfn) | |
proc second(n: int):int = | |
n * 1000 | |
echo first(@[5, 6, 3, 2, 0], system.cmp[int], second) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment