/*

  ~*~*~*~*~*~*~
  * tilde30.6 *
  ~*~*~*~*~*~*~

  day-01: 2026-09-01 (Tue)
  ========================

  # what is this thing called go?

  i will be looking at the tour of go at

=> https://go.dev/tour/

  but first,

=> https://go.dev/doc/tutorial/getting-started

  because i want to know how to use go
  locally (i used it before but it's been
  a while).

  ---

  ## professional tracker

  apparently one should enable "dependency tracking",
  like this.

  $ go mod init example/hello

  > This creates a go.mod file at the root of your source tree.
  > Dependencies you add will be listed in that file.

  cf. https://go.dev/doc/modules/managing-dependencies#naming_module

  sounds alright.

  so i'm gonna run:

  $ go mod init 'tilde.town/~fruit/t30.6'

  ok, let's go!

  => https://www.youtube.com/watch?v=AWM5ZNdWlqw

  so...

  $ go run . # or go run day-01.go
  > day-01
  > =======
  > ok let's go!
  > ...

  success :)

  one can also build a binary with

  $ go build .

  cf. https://gobyexample.com/hello-world

  ---

  # kl. 18.34

  started also reading "The Go Programming Language".

  TGPL - 0. PREFACE
  ====================

  interesting: "squeak", and then "newsqueak" (1989),
  programming languages "for communicating with mice". that
  appeals to me.

  > The first was called Squeak
  > "A language for communicating with mice", which provided
  > a language for handling mouse and keyboard events,
  > with statically created channels.

  => https://en.wikipedia.org/wiki/Newsqueak

  i am curious what this channel thing in go
  will be all about (communication & synchronisation &c.)

  >, [...] a pernicious change trades simplicity for its
  > shallow cousin, convenience. Only through
  > simplicity of design can a system remain stable,
  > secure, and coherent as it grows.

  ---

  got sidetracked reading about the "wav" file format.
  also doodling a gopher and talking to bf about
  his uni studies. tomorrow he's gonna have
  cell biologi, i am jelly.

  ---

  > communicating sequential processes (CSP),
  > embodied by "goroutines" and "channels"

  => https://go.dev/wiki/GOPATH

  not sure i get that tbh. the book is from 2015, so
  it might teach deprecated things.

  $ go version
  > go version go1.26.7-X:nodwarf5 linux/amd64

  while the book uses go1.5


  TGPL - 1. TUTORIAL
  ===================

  packages
  =========

  - made of one or more .go files in a directory
  - each .go file start with a "package" declaration
    (which pkg does the file belong to)
    followed by a list of imports, followed by
    declarations of the file

  > Package main is special. It defines a standalone
  > executable program, not a library.

  like C etc.

  semicolons
  ==========

  > Go does not require semicolons at the ends of
  > statements or declarations

  sejt!

  > For instance, the opening brace { of the function must
  > be on the same line as the end of the func declara-
  > tion, not on a line by itself

  :(

  > in the expression x + y, a newline is permitted after but not
  > before the + operator

  makes sense.

  gofmt
  =====

  to replace the current buffer in (n)vim with the formatted
  output, i can run (in normal mode):

  :%! gofmt


  1.2 Command line args
  =====================

  slices
  ======
  - os.Args is a slice of strings
  - slices are dynamically sized sequences
  of array elements
  - length with "len(slice)
  - zero-indexing
  - slice[i] for single elem access
  - slice[i:j] (i inclusive, j exclusive)
    for subsequences (like python)
  - i defaults to 0 if omitted,
    j defaults to len(slice)
*/

/*
> By convention, we describe each package in a comment
> immediately preceding its package declaration."
cf. TGPL 1.2  (p. 5)
*/
package main

import (
	"fmt"
	"os"
	"strings"
	"time"
)

func main() {

	/*
	 TGPL - 1.1 HELLO WORLD
	 =======================
	*/

	fmt.Println("day-01")
	fmt.Println("=======")
	fmt.Println("ok let's go!")

	// "Go natively handles Unicode"
	// :)
	var msg string = "halløj!" // 'ø' takes two bytes in utf-8 encoding.
	fmt.Println(msg)
	// i mean this also works in C
	// len gives the number of bytes of the string as utf-8. also like C
	for i := 0; i < len(msg); i++ {
		// this prints the individual utf-8 bytes as numbers. kewl.
		fmt.Println("char ", i, " is '", msg[i], "'")
	}

	// Print vs Println separator:
	// ugh: "Spaces are always added between operands" (fmt.Println)
	// cf. => https://pkg.go.dev/fmt#Println
	fmt.Println("the message '", msg, "' has ", len(msg), " bytes (NOT glyphs).")
	// but: "Spaces are added between operands when neither is a string" (fmt.Print)
	// cf. => https://pkg.go.dev/fmt#Print
	fmt.Print("the message '", msg, "' has ", len(msg), " bytes (NOT glyphs).\n")

	/*
	  TGPL - 1.2 COMMAND-LINE ARGUMENTS
	  ==================================
	*/

	// cf. their "echo" example on p. 5
	var out, sep string
	for i := 1; i < len(os.Args); i++ { // NOTE: no prefix increment :(
		// smart: sep is initialised to the empty str
		out += sep + os.Args[i]
		sep = " "
	}
	fmt.Println("echo prints:", out)

	// > after the first iteration, a space is also inserted so that when
	// > the loop is finished, there is one space between
	// > each argument.  (TGPL, p. 5)
	//
	// ok, yeah makes sense!
	//
	// > This is a quadratic process that could be costly if the number
	// > of arguments is large, but for echo, that’s unlikely
	//
	// what? why is it quadtratic? because it creates a new string
	// for each += assigment?
	// NOTE: explained on p. 8 :)

	// range for loops:
	out = ""
	sep = ""
	for _, arg := range os.Args[1:] { // _ is the (here unused) idx
		out += sep + arg
		sep = " "
	}
	fmt.Println("range echo prints:", out)

	// efficient echo without creating a new string on each iter (p.8)
	fmt.Print("strings.Join echo prints: ")
	fmt.Println(strings.Join(os.Args[1:], " "))

	// hmm, what if we do
	amogus := "123ඞ"
	for i, ch := range amogus {
		fmt.Print("char ", i, " is '", ch, "'\n")
	}
	// cool, this prints unicode codepoints (decimal)!
	// so...
	for i, cp := range "halløj!" {
		fmt.Print("char at byte ", i, " is unicode codepoint '", cp, "' (decimal)\n")
	}
	// note i still denotes the byte we are in (and not code point),
	// so i skips from 4 to 6 after the "ø" (as "ø" takes two
	// bytes in utf-8 (here, "ø" is realised as "Latin Small Letter O With Stroke",
	// but there are also combining characters etc. hmm

	fmt.Println("~~~")

	// Exercise 1.1: also print os.Args[0], i.e. the name of the command
	fmt.Println("Ex 1.1 echo:", strings.Join(os.Args, " "))

	// Exercise 1.2: Modify the echo program to print the
	// index and value of each of its arguments, one per line
	fmt.Println("Ex 1.2 echo:")
	for i, arg := range os.Args[1:] {
		fmt.Println(i, arg)
	}

	// Exercise 1.3: profile running time between dumb and strings.Join echo
	fmt.Println("Ex 1.3 perf:")
	perf_iters := 4 // increase me
	var t0 time.Time

	t0 = time.Now()
	for i := 0; i < perf_iters; i++ {
		dumbEcho()
	}
	dumb_time := time.Since(t0).Milliseconds()

	t0 = time.Now()
	for i := 0; i < perf_iters; i++ {
		smartEcho()
	}
	smart_time := time.Since(t0).Milliseconds()

	fmt.Println("dumb echo:", dumb_time, "ms")
	fmt.Println("smrt echo:", smart_time, "ms")

	// result: smart echo is indeed faster, but only
	// if like a certain threshold of command line
	// args is passed to the program; otherwise,
	// the first echo version running usually runs
	// faster no matter if smart or dumb
	// (probably garbage collection or sth)

	// $ go run . i am a little teapot and i have really bad orthodontic issues and always get distracted my fellow gophers
	// > dumb echo: 16 ms
	// > smrt echo: 10 ms
	// but
	// $ go run . gay sex
	// > dumb echo: 5 ms
	// > smrt echo: 8 ms
	// (actual time varies)
}

func smartEcho() {
	fmt.Println(strings.Join(os.Args[1:], " "))
}

func dumbEcho() {
	var out, sep string
	for _, arg := range os.Args[1:] {
		out += sep + arg
		sep = " "
	}
	fmt.Println(out)
}
