Kotlin - Testing

Writing tests in Kotlin can be done using the JUnit and KotlinTest frameworks. These frameworks provide a way to write and run tests for your Kotlin code. JUnit is a popular choice for unit testing in Kotlin due to its simplicity and extensibility. Writing Tests JUnit provides a set of annotations that can be used to write tests. The @Test annotation is used to mark a method as a test method. The @Before and @After annotations are used to mark methods that should be run before and after each test method, respectively. ...

C# - Testing

C#, NUnit has a lot of features that makes it a good choice for testing. It provides features for writing and running tests, and also for creating test fixtures and test suites. NUnit is a popular choice for unit testing in C# due to its simplicity and extensibility. Writing Tests NUnit provides a set of attributes that can be used to write tests. The Test attribute is used to mark a method as a test method. The TestCase attribute is used to provide test data for parameterized tests. The SetUp and TearDown attributes are used to mark methods that should be run before and after each test method, respectively. ...

Go - Testing

Unit tests in Go can be written using testing package. We require to create a file with _test.go suffix to write tests for a package. Conventionally, the test file should be in the same package as the code being tested. The test file should import the testing package and the package being tested. eg: . ├── main.go └── main_test.go Writing Tests Suppose we have a function Add in main.go which adds two numbers. ...

Parser - An Example in Go

A Parser is a program that reads the tokens and converts it into an abstract syntax tree (AST). It is the second part of an interpreter. What the usage looks like // for an input `let five = 5;` input := `let five = 5;` l := lexer.New(input) p := parser.New(l) // result is a list of statements result := []ast.Statement{ &ast.LetStatement{ Token: token.Token{Type: token.LET, Literal: "let"}, Name: &ast.Identifier{ Token: token.Token{Type: token.IDENT, Literal: "five"}, Value: "five", }, Value: &ast.IntegerLiteral{ Token: token.Token{Type: token.INT, Literal: "5"}, Value: 5, }, }, } input2 := "1 + 2 + 3;" l2 := lexer.New(input2) p2 := parser.New(l2) result2 := []ast.Statement{ &ast.ExpressionStatement{ Token: token.Token{Type: token.INT, Literal: "1"}, Expression: &ast.InfixExpression{ Token: token.Token{Type: token.PLUS, Literal: "+"}, Left: &ast.IntegerLiteral{ Token: token.Token{Type: token.INT, Literal: "1"}, Value: 1, }, Operator: "+", Right: &ast.InfixExpression{ Token: token.Token{Type: token.PLUS, Literal: "+"}, Left: &ast.IntegerLiteral{ Token: token.Token{Type: token.INT, Literal: "2"}, Value: 2, }, Operator: "+", Right: &ast.IntegerLiteral{ Token: token.Token{Type: token.INT, Literal: "3"}, Value: 3, }, }, }, }, } The parser also needs to handle operator precedence and associativity. It is a complex part of an interpreter. ...

Lexer - An Example in Go

A Lexer is a program that reads the code and converts it into tokens. It is the first part of an interpreter. What the usage looks like // for an input `let five = 5;` input := `let five = 5;` l := lexer.New(input) // result is a list of tokens result := []tokens.Token{ {Type: tokens.LET, Literal: "let"}, {Type: tokens.IDENT, Literal: "five"}, {Type: tokens.ASSIGN, Literal: "="}, {Type: tokens.INT, Literal: "5"}, {Type: tokens.SEMICOLON, Literal: ";"}, {Type: tokens.EOF, Literal: ""}, } input2 := "1 + 2 + 3;" l2 := lexer.New(input2) result2 := []tokens.Token{ {Type: tokens.INT, Literal: "1"}, {Type: tokens.PLUS, Literal: "+"}, {Type: tokens.INT, Literal: "2"}, {Type: tokens.PLUS, Literal: "+"}, {Type: tokens.INT, Literal: "3"}, {Type: tokens.SEMICOLON, Literal: ";"}, {Type: tokens.EOF, Literal: ""}, } Let’s see how to implement a sample lexer in Go. ...

Interpreter - Overview

An interpreter is a program that reads and executes code. It is a way to execute code without compiling it. It is a great way to execute code on the fly. It is used in many places like scripting languages, command line tools, etc. Parts of an Interpreter ( Simplified ) A minimal interpreter can be represented in 3 parts: lexer: It reads the code and converts it into tokens. parser: It reads the tokens and converts it into an abstract syntax tree (AST). evaluator: It reads the AST and executes the code. Note: There can be more parts like optimizer, IR generator etc. for advanced interpreters. ...

Grammar For A Simple Language

Grammer in computer science is a set of rules that defines the structure of a language. It defines a language in a structured way and parsers are built based on it. BNF Backus-Naur Form, or BNF, is a notation technique used to express context-free grammars. It is used to define syntax of programming languages, datastructures, etc. EBNF Extended Backus-Naur Form, or EBNF, is a notation technique used to express context-free grammars. It is an extension of BNF. ...

Scala - Overview

Scala is a jvm based programming language. Scala is widely used in big data processing, web applications, and microservices for its scalability and performance. The code is compiled to Java bytecode and can be executed on the JVM. Scala is known for its strong static type system, concise syntax, and functional programming features. Few things I like about Scala are The expressive syntax and powerful type system. The functional programming features like pattern matching, higher-order functions, and immutability. The seamless interoperability with Java, which allows us to use existing Java libraries and frameworks. Few things I dislike about Scala are ...

Caching Patterns

Caching is one of the critical solution to improve performance and reduce latency in data access. Cache is a fast and temporary storage ( generally RAM ) When using cache there are different patterns in which we can implement reading the cache data and writing the cache data. Cache Aside Ideal where caching everything is not critical for usecase nor necessary. Application and Datastore control the data, and cache is an optimization sidecar. ...

Go - Factory Pattern

In golang, we use interfaces to define a contract for a particular type. Factory pattern uses this interface to create instance / object of a particular type like Storage, Service, Document etc. Implementing Factory pattern Define an interface with a method to create the object. package factory type Document interface { Render() string } Create different types which implement the interface. package factory type PDF struct { data string } func (p *PDF) Render() string { return "PDF: " + p.data } type Word struct { data string } func (w *Word) Render() string { return "Word: " + w.data } Create a factory function which returns the object based on some condition. package factory func NewDocument(docType string, data string) Document { switch docType { case "pdf": return &PDF{data: data} case "word": return &Word{data: data} default: return nil } } Example usage func main() { pdfDoc := DocumentFactory("pdf") wordDoc := DocumentFactory("word") pdfDoc.Render() wordDoc.Render() } This pattern is useful when we have different implementations of similar Interfaces like postgres storage, redis storage etc.. and It also helps to switch between these implementation if they’re interchangable. ...