Skip to content

Scare-Security/Basic-Crystal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 

Repository files navigation

Introduction

Like most tutorials here we will be talking about the crystal programming language which is a compiled ruby syntax like programming language designed for server side development and automotive systems. This tutorial will go into data types, JSON, ECR, Classes, Modules, Methods, Method Arguments, Arrays, Loaders, Servers and finally building your own router to understand exactly how crystal works as a programming language

Overview of crystal

Crystal was a language that is still in the experimental phases which was released back in 2014 with a idea to be more like ruby but compiled. This language is used mainly for server side development and as defined by https://nikolamotor.com/ used as a base for automotive systems. This language is a really odd one but fits a wierd syntax for a compiled language. This language is reallyt for people who also enjoy the ruby syntax with most things such as basic variables, routers, importing and modules and classes being setup differently.

The basics

Crystal is an easy language to get around and you can understand such as deep amount about it if you come from ruby. For example below is how you initialize variables.

variable1 = "Data" 

you can also init variables with @ symbols which make them instance variables for example.

@var : String 
@var2 : String | Int64

you can use the | to make it a or operator saying that variable can be either String or Integer64. This actually is a decently typed and developed system for variables as most languages do not allow you to do that.

you can also assign multiple variables at once

a, b, c = 1, 2, 3

pretty simple and readable right?

well now you can also output those statements and variables in different ways using puts like so.

a = 1
puts a
puts "#{a}"

what about methods? Methods in crystal are a bit wackier to some and have some really useful ways of initializing variables. First off like ruby you can call what function or variable of the method you are assinging a variable to. For example

def function2(data)
  puts data
end

function2(data: "value name")

which makes it alot easier to assign certain values using those functions. there are a few ways of defining data as well as you can define the data type of the variable inside of the method like so

def (x : String) 
  puts x
end

x must be a string for you to work with it. Like definitions and methods we have classes and modules. Starting a class is simple in crystal just use the class keyword followed by the class name and a definition.

class Classname 
  def task
    "data" + self
  end
end

what this class does is defines a method called task and under that returns or adds a string to the current value so if you wanted to call that function or method you would use.

class Classname 
  def task
    "data" + self
  end
end

def Classname.askin
  "Data value two"
end

puts Classname.askin

will output

Data value two

The reason this happens is because we are using the class to define a new method not the same method. Also do note that we would need to construct a class named String to make this output the way we need to. So for example

class String
  def task
    "data" + self
  end
end

puts "more data".task 

this will output

more data data

because we called the class name with the data type then proceeded to output a string then adding .task the name of our method under that class. Doing this with other data types is a bit hard as for some reason crystal sees String as a class but every other data type as a structure. So if you switch class String to class Int it will call it a struct and error out.

this makes code time alot more efficient the further you get into the language and gives you the most basic understanding of how methods can be used. Functions and methods also have return types which you can call in two ways. if you want more than one argument you use {datatype, datatype} and if you want to return only one data type you use :

for example say we have a method that adds two values and returns the final single value

def multiply(x : Int, y : Int) : Int
      return x*y
end

will return of typer integer and return the multipled values. So in the after definining a function you can go ahead and mark the return type after the () with : . Now as said before we can use a list of return types using {} which looks a little like this \

def afunction : {Int, String}
  return 1, "some string"
end

Do you understand how helpful this can actually be? I think this is very neat because of how interesting the type system works with methods and in general. This type of definition will help you in later more advanced code bases with crystal. As you can see the basics of crystal are easy but it does get a bit wackier towards the end but either way still pretty good for a compiled language right?

  • Task for this section: Build a basic application that will take the input of a single strign using a class and mash the first and last name together where the first name is static. Do not forget that definitions can not start with a capital letter because it then becomes constant.
View Assignment code
class String
  def lastname
    "bobert " + self
  end
end

puts "Data".lastname

Classes and Modules

Classes are a bit wacky but are fun in crystal. Crystal has an amazing way to define classes and modules. The example below is off a simple module with a class which will output the data parsed inside of the class. Note that every module with a class must have an initializer if you want to run special rendering functions ( we will get more into that in the ECR section )

module Base 
  class Initializer
  end
end

This is a simple module with a nested class named Initializer. So if you wanted to call the module and class you would use

a = Base::Initializer.new

despite there being no new or init function every module with an inline class must end with .new

anytime you want to use a variable that the class will accept as an argument you have to define an initialize definition, this is standard. Below is an example of a Module with a nested class that uses the initialize method to make an argument public through the entire class.

module Base
  class Initializer 
    def initialize(@data : String | Nil)
    end
    def caller
      puts "#{@data}"
    end
  end
end

a = Base::Initializer.new("value")
a.caller()

we first define a module named base with a class named Initializer. Under the class is the used initialize function with one argument that is named @data of data type String or Nil this means that the value can be empty without raising any errors. After the initialize function was created the caller method prints out the value of @data. Now that we have the class setup we can call the .new method for the module->class with the argument for the initialize function. Once done we can use the variable a to call the caller function under the Initializer class. a.caller() will output value

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published