You may have heard notices of the Crystal programming dialect recently. It is a dialect that looks fundamentally the same as Ruby. Indeed, numerous Ruby projects are additionally legitimate Crystal programs. Be that as it may, it must be underlined this is an insignificant symptom of the sentence structure of the dialect and is not an objective of the venture.

A standout amongst the most fascinating things about Crystal is that it is a statically sort checked dialect, yet it doesn't require the software engineer to sprinkle sorts wherever like Java. Precious stone orders down to effective code, which implies Crystal programs are substantially quicker than Ruby projects.

In this article we will take a snappy jump into Crystal. This is in no way, shape or form a complete stroll through of the considerable number of highlights in Crystal. Rather, we will build up a simultaneous Chuck Norris joke fetcher with the focal point of a Rubyist. This includes influencing HTTP To get demands and furthermore some JSON parsing.

We will perceive how far that takes us, alongside investigating the offices that Crystal gives that makes things more advantageous.

Getting Crystal 

I will tenderly direct you to the establishment manage since it would without a doubt make a far better showing with regards than with covering establishment for the different Linux dispersions, Mac OSX, and other Unix frameworks. For the MS Windows clients out there: Sorry! Gem requires a Linux/Unix based framework.

The Sequential Version 

We start with the consecutive form first. To begin with, we require a HTTP customer to get the jokes. Our information will originate from The Internet Chuck Norris Database. So as to recover a joke, you simply need to shout to the URL, for example,

http://api.icndb.com/jokes/123

This profits:

{
  "type":"success",
  "value":{
    "id":123,
    "joke":"Some people wear Superman pajamas. Superman wears Chuck Norris pajamas.",
    "categories":[
    ]
  }
}

We should make another class and name it chucky.cr. While we are grinding away, we might actualize Chucky#get_joke(id):

require "http/client"
require "json"

class Chucky
  def get_joke(id)
    response = HTTP::Client.get "http://api.icndb.com/jokes/#{id}"
    JSON.parse(response.body)["value"]["joke"]
  end
end

c = Chucky.new
puts c.get_joke(20)
Precious stone comes worked in with a HTTP customer and JSON parser. We should take a stab at running this in the terminal, which is finished by passing the document name to the gem charge:

$ gem chucky.cr

The Chuck Norris military unit was not utilized as a part of the diversion Civilization 4, in light of the fact that a solitary Chuck Norris could crush the whole joined countries of the world in one turn.

Incredible achievement! Up until this point, so great. Let's assume we need to recover a group of jokes. Appears to be truly clear:

class Chucky
  ...other methods...

  def get_jokes(ids : Array(Int32))
    ids.map do |id|
      get_joke(id)
    end
  end

end
The primary thing you'll see that is not quite the same as Ruby is that the sort of ids is as a rule unequivocally characterized as Array(Int32). This is perused as "an Array of Int32s". To be clear, we could have forgotten this. In any case, since I'm almost certain that ids are dependably Int32s, I need to be to a great degree clear and stay away from missteps, for example,

c = Chucky.new
puts c.get_jokes(["20"])
Actually, when you have a go at running this, you'll get an arrange time blunder:

Mistake in ./chucky.cr:50: no over-burden matches "Chucky#get_jokes" with sort Array(String) Overloads are:

Error in ./chucky.cr:50: no overload matches 'Chucky#get_jokes' with type Array(String) Overloads are:
 - Chucky#get_jokes(ids : Array(Int32))
puts c.get_jokes(["20"])
   ^~~~
The sharp peruser would bring up that it clears a path more sense to indicate the sort on the contention in Chucky#get_joke rather, and she would be totally right. Actually, you can likewise indicate the arrival kind of the technique:

class Chucky

def get_joke(id : Int32) : String

# ...

end

def get_jokes(ids : Array(Int32)) : Array(String)

# ...

end

end

c = Chucky.new

puts c.get_jokes([20]) # <- - Change this back to an Array(Int32)

How about we attempt once more:

% gem chucky.cr

Blunder in ./chucky.cr:53: instantiating "Chucky#get_jokes(Array(Int32))"

puts c.get_jokes([20])

^~~~~~~~~

in ./chucky.cr:20: instantiating "get_joke(Int32)"

get_joke(id)

^~~~~~~~

in ./chucky.cr:24: sort must be String, not JSON::Any

def get_joke(id : Int32) : String

^~~~~~~~

Whoops! The compiler discovered something! So it appears like Chucky#get_joke(id) doesn't restore a String, however rather it restores a JSON::Any. This is awesome, on the grounds that the compiler has gotten one of our awful suppositions.

Presently we are left with two decisions. It is possible that we change our Chucky#get_joke[s] to return JSON::Any or we keep utilizing String. My vote is for String, in light of the fact that any customer code shouldn't mind that the jokes are of JSON::Any. We should adjust the Chucky#get_joke(id). For good measure, we additionally handle the situation where there's some parsing mistake and essentially restore a void String:

class Chucky

# ...

def get_joke(id : Int32) : String

reaction = HTTP::Client.get "http://api.icndb.com/jokes/#{id}"

JSON.parse(response.body)["value"]["joke"].to_s safeguard ""

end

end

Everything should run fine at this point. We have a slight issue, however. Attempt to envision what happens when we do this:

c = Chucky.new

puts c.get_jokes[20, 30, 40]

In our present usage, the jokes will be brought successively. This implies the time take for Chucky#get_jokes(ids) to finish is the aggregate time taken to bring each of the three jokes.

We can improve the situation!

The Concurrent Version

Since we have influenced it to work, how about we influence it to quick. Gem accompanies a simultaneousness primitive called filaments, which are fundamentally a lighter-weight variant of strings. The other simultaneousness primitive are channels. On the off chance that you have done any Golang, this is essentially a similar thought. Channels are a path for filaments to impart without the migraines of shared memory, locks, and mutexes.

We will utilize the two strands and channels to simultaneously get the jokes.

Here's the principle thought. We will make a divert in the primary fiber. Each call to Chucky#get_joke(id) will be done in a fiber. Once the joke is brought, we will then send the channel the outcome.

class Chucky

# ...

def get_jokes(ids : Array(Int32)) : Array(String)

# 1. Make divert in the fundamental fiber.

chan = Channel(String).new

# 2. Execute get_joke in a fiber. Send the outcome to the channel.

ids.each do |x|

bring forth do

chan.send(get_joke(x))

end

end

# 3. Get the outcomes.

(1..ids.size).map do |x|

chan.receive

end

end

end

To start with, we make a channel. Note that we have to indicate the sort of the channel.

Next, we execute get_joke(id) in a fiber. This is done in a bring forth piece. When we get an outcome from get_joke(id), we send the outcomes to the already made channel.

Sending a channel an esteem is just a single bit of the astound. So as to get an incentive out of a channel we have to call Channel#receive. Each time we get back to get we get one esteem. On the off chance that there are not esteems (yet), it will piece. Since we know the extent of ids, we simply need to call Channel#receive ids.size times.




0 comments:

Translate

GoogleTech786. Powered by Blogger.

Subscribe Youtube

Our Facebook Page

Wikipedia

Search results

Popular Posts

Adsense