Apart from that I wish PyPy were completely cpython 3.6-compatible for all platforms, and the main implementation, for performance and speed reasons, there is nothing directly bad about Python, for a dynamically typed language. Previously, I would have said it needed good string formatting, but with the new f-strings, I don't really feel that's a problem. It would also be nicer if there was a universal, consistant and simple way to package python applications into nice non-python-requiring distributables, but there are (slightly painful) ways to now.
That's not to say that there isn't things I like in other languages that I wish Python were to have: Ruby's blocks are nice, for example, but they're not things whose absence makes Python bad.
Yes, I wish there were a static language based on Python, something like Crystal is attempting to become for Ruby, but I wouldn't want Python itself to be static, that's not what it is.
Now, I vastly prefer Crystal to Go, but let's be fair. In order to be a better Go than Go, they need to support proper parallelism. Go's big selling point is its handling of concurrency, and while Crystal has concurrency, everything executes in one system thread (except parallel GC).
The two big things holding Crystal back on a technical level are lack of threading and lack of official Windows support. Other than that it is a very nice language.
require "http/client"
response = HTTP::Client.get("http://www.example.com")
content = response.body.gets_to_end
You can read more at https://crystal-lang.org/api/0.28.0/HTTP/Client.html
I assume that several of the top backers use Crystal in productions: https://crystal-lang.org/sponsors/
Your not going to pay 250 to 2000 dollar / month in donations, if you do not use crystal to make money.
Most of my work with Crystal has evolved around testing and seeing how it stacks up against Go for our projects. Speed wise its in the same range as Go just the compiler being a lot slower.
Its most power for any company that has a Ruby background, is the more or less the "drop in replacement" ( with a bit or work). Its not like your going to rewrite your entire stack, unlike going to a other language.
My own tests comparing it to a few scripting languages ( like Ruby, PHP ) has Crystal crushing them ( no big surprise ). We are talking realistic routing, DB access reads from a cluster DB, Json REST Api etc... From this point of view its plenty production ready.
The main issue is frankly, the slow compilation speed ( compared to Go and the "quick and dirty" scripting languages ) and the slow development speed of the language. I like to see Crystal going to a fixed release schedule like Go/Rust, where you more can anticipate official feature releases.
Now if a company has the balls to put 2000 dollar per month on the line to sponsor the language, ... that sounds a lot like a ringing endorsement for the language in production.
If I'm allowed to use characters 0-9,a-p I can offer 6 seconds:
require "big/big_int" puts (BigInt.new(2) ** 74207281 - 1).to_s(26)
time:
real 0m5.944s user 0m5.956s sys 0m0.064s
> - Have a syntax similar to Ruby (but compatibility with it is not a goal)
> - Statically type-checked but without having to specify the type of variables or method arguments.
> - Be able to call C code by writing bindings to it in Crystal.
> - Have compile-time evaluation and generation of code, to avoid boilerplate code. Compile to efficient native code.
Not sure about testing, but some comments on performance.
Obviously it's going to depend a lot on the number of clients and logic complexity. Not sure about the issues with multi-threading benefits now, but last I learned about threads in Ruby, MRI was quite limiting with Global Interpreter Lock, but JRuby did not have these issues, so you might want to look at that implementation later.
If you're not using too many gems and still have performance problems, you might also prefer to use crystal lang which is supposed to have Ruby like syntax (very easy to port) and C performance.
Man, just want to shout out to Crystal!
That is one seriously comfy language that compiles to very fast native. If anyone reading this has any soft spot for Ruby, but also likes (optionally) typed languages, you must look at Crystal.
> The possible solution suggested by Matz is to rely on something that helps to reconstruct the missing information that developers may need. That is type inference.
Reminds me of Crystal.
What you are attempting to do is technically possible, but it's not exactly what ruby is great at.
In other languages like C, the code goes through a compilation step where the code is translated from text (source code) into computer instructions (a binary or executable). The resulting binary file can be distributed and then others can run it on their computer without needing to know anything about the language it was originally written in.
Ruby, on the other hand, is an interpreted language. There is no way to take ruby source code and turn it into computer instructions. In order to run ruby code, you need something that can take the code and interpret it. So, if you were to distribute your ruby program to others, they would need to have ruby installed in order to run it.
This is why ruby is a great language for all things server side. When you set up your server, you just need to have ruby installed and then it'll run your code. This is also why ruby isn't great for all things client side, because it requires the client to install things.
One way around this limitation is to also include a ruby interpreter along with your source code. There are some projects out there that attempt to do just that, each with their own limitations and degrees of success. One such project is https://github.com/pmq20/ruby-packer. With this, you can give it your ruby code and it will bundle it up with a ruby interpreter so that you can hand out a single executable file to run.
Depending on what you're doing, that might be good enough for you. If not, you may want to consider using a compiled language. Crystal (https://crystal-lang.org/) is a compiled language based on ruby that might work well for you, though it is still in its infant stages in terms of third party libraries.
They could always port it to Crystal, which has extremely good performance (faster than Go in most micro-benches) and it is quite compatible with the Ruby language, although it would need some work to fully port.
From what I can tell, not fully. Which is really disappointing if they're going to call it a 1.0 release without supporting the world's most popular OS.
This is how you get written off as a toy language and not taken seriously. If I sound bitter, it's because I really am. I've tracked this project for years, donated to the core team, written a sideproject app in Kemal, and I would love to see an actual, production-ready version of Crystal. That's what 1.0 should signify. Instead, it seems like they're calling it 1.0... just because?
From the announcement that was (over a year ago at this point):
> "The challenge at hand is to get as quickly as possible to a 1.0 version of Crystal that is at the same time as faithful as possible to the current state of the language, stable enough for individuals and organizations to feel comfortable adopting it for even their highest impact projects, and a solid foundation for future major versions."
Not having Windows or concurrency support is neither of those things. Why is, "as quickly as possible," a goal?
To be perfectly clear, I'm not bitching about the speed or timeline. I'm bitching about the weird decision to designate a half-baked release as 1.0, which is going to turn off a lot of people that could otherwise consider using Crystal in production some day. Not to mention organizational support. I work as a cloud engineer, and we write a lot of scripts to drop onto (Windows AND Linux) servers to automate tasks. If I floated using this proposed 1.0 to my boss, he would just laugh. I wouldn't blame him either. Guess I'll stick with Go.
Crystal is a statically typed programming language inspired by Ruby: https://crystal-lang.org/
Kind of like having the concurrency and performance of Go with the syntax of ruby. It overall looks really great though I have little hope of it ever being more than a niche hobbyist language.
Glad you're excited about Crystal :)
FYI, In the "exception handling" section, it can be shortened further to just:
def self.mount?(path) stat_path = File.lstat(path) rescue Errno # It doesn't exist so not a mount point return false end
The begin
statement is implied in any block: https://crystal-lang.org/docs/syntax_and_semantics/exception_handling.html#short-syntax-form
Or crystal if GP wants something compiled.
Both are great languages that have a better and saner concurrency model than ruby while sharing a lot of similarities in syntax.
I think more people would use Lisp or Haskell or OCaml, but those languages never had a large community focused on making the tooling around the languages better. Rubyists take for granted that Bundler and RubyGems.org came along and made dependency management as easy as it was. Making and distributing packages for Ruby is one of it's best features, and it's something that people have replicated in multiple other languages, Cargo for Rust now Yarn for Javascript. Both of which happen to be designed by the person who designed Bundler. Besides it's minimalist flexible syntax, Ruby is to me at least, one of the most expressive languages to come out of the 90's language boom. Even if Matz's interpreter fades away, the syntax and ideas of Ruby will live on (see Crystal, and RubyTruffle).
But Crystal has pointers! https://crystal-lang.org/api/0.19.4/Pointer.html
Yes, they are unsafe and you shouldn't normally use them. But we use them to implement basic types like Array and Hash, and to interface with C libraries in a super-easy way. And if you have a piece of code that is a bottleneck and you eventually realize you might do it much faster with raw pointers, maybe with a bit of unsafe code, Crystal lets you do it.
This is why I like to think of Crystal as both a high-level and low-level language: it has nice high-level things like array literals, hash literals, OOP, mixins, macros, compile-time stuff, multidispatch. But it also has pointers, C bindings, stack-allocated fixed-length arrays (StaticArray: https://crystal-lang.org/api/0.19.4/StaticArray.html ), etc. You can even take a pointer to a local variable or an instance variable. You normally don't need to do that, but if you want, you can.
Your last paragraph makes a bit of sense, but not entirely. Rust for example lets you do unsafe stuff, but it's still a great language because you normally don't need to do that, you use abstractions over those unsafe things. In Crystal it's exactly the same.
Crystal has Enums which they prefer using over Symbols as most of the time you are working with a finite number of values that can be passed in. You can even pass in Symbols to methods that accept an Enum, and the compiler will map them to the Enum value; both test(:ONE)
and test(:one)
will map to MyEnum::ONE
. That said, I kind of like having the ability to accept arbitrary Symbols to allow extending an API. Maybe in the future Ruby could add something like keyword arguments but for restricting Symbols (ex: def foo(type: [:foo, :bar, :baz])
) for when you only want to allow a finite number of Symbols?
Crystal doesn't allow @instance_variable
or @@class_variables
at the top-level (outside of a class). You can, however, use a plain variable like so:
foo = "foo"
responds_to?
method (with an s), and that works for me, with and without self
.include?
-> includes?
, key?
-> has_key?
) and keep an eye for the more subtle differences (like each
returning nil
in Crystal instead of self
).nil
unless you are explicit about it (not_nil!
, the getter!
macro, as
casts...).rescue => ex
-> rescue ex
my_var.tap(&:my_method)
-> my_var.tap(&.my_method)
my_var &.my_method1 &.my_method2
-> my_var.try &.my_method1.my_metod2
Porting a big Ruby app to Crystal is not something that can be done quickly and on a whim, but it certainly is easier that porting from any other language.
Hey, great that you want to try Crystal. It's really an amazing language and I hope you get to know it well ;) I'll try to answer your questions as far as I know:
[src/gc/boehm.cr](https://github.com/crystal-lang/crystal/blob/master/src/gc/boehm.cr)
, which is mostly just bindings to LibGC. Boehm GC is considered to be good enough for the current state of Crystal's development but it is clear that it will need to be replaced eventually, probably by a customized native-Crystal. There is an issue currently discussing the use of immix GC which is used by scala-native on LLVM. You can also disable garbage collection entirely (-Dgc_none
compile flag) but this obviously won't work with the stdlib (there was some project working on a minimalistic stdlib for embedded use, but I can't remember what it is called). It should even be possible to use a custom GC for specific requirements. So, currently, there is certainly room for improvement, but the maintainers are aware of this and there are ideas how to develop further.map
etc.That's basically the reason why I wrote this blog post: https://crystal-lang.org/2016/07/15/fibonacci-benchmark.html
But it can't be helped, fibonacci and factorial are one of the easiest and simplest programs to compare benchmarks.
Also note that in my article I talk about adding the possibility of mutating BigInt, and I think we'll eventually add that into the standard library.
Well the Crystal Programming language has reached 1.2 now(actually 1.2.2 to be precise). The title of this post made it look like the language just hit the 1.0.0 milestone, it is not.
Array(Array(Int))
is what you could use in a type restriction. For a method parameter or return value at least.
EDIT: Crystal has various chat channels that might be easier for quick questions like this: https://crystal-lang.org/community/#chat.
The more modern approach would be
file_data = {{ read_file "#{DIR}/README.md" }}
If I understood correctly, you need an array of the filenames so that they can later be used for selection.
Then (if I am correct), you can create an empty array of string outside the Zip::File.open block
And then inside the file.entries.each do |entry|
block, do Array#push (https://crystal-lang.org/api/0.32.1/Array.html#push(value:T)-instance-method)
>When I use other languages, I sometimes wonder if they were optimising for programmer frustration instead.
ROFL. That made my day. Thank You.
Questions.
And again, Thank you for your amazing work.
Instance vars can be modified from outside the current scope in a concurrent environment. Thus the value of `@list` can theoretically change between the not-nil-check `@list` and the call to `@list.empty?`.
Local vars are only visible in the current scope and the compiler can make sure there is no chance of external modification.
See https://crystal-lang.org/reference/syntax_and_semantics/if_var.html#limitations
`HTTP::Server#listen` has a `reuse_port` option ( only works on linux I belive ). This lets you run multiple instances of your server that will all listen on the same port.
> So, yeah, mainly frustration. But I won't intervene anymore from now on. I'll let the language flow without me, maybe without my negativity it will reach a good port. I really hope so!
Hey, /u/asterite I understand your concerns. You wrote almost all the compiler by yourself. But there is a lot of people that still like crystal and want it to become a nice language.
Can you share us some guides before you leave?, I mean, can you inherits us your knowledge about crystal internals a bit more. There are a lot of developers than can collaborate in the compiler itself (not just stdlib) but we don't have any guide or specification about how crystal do all stuff. By example:
How codegen works? How inference type works? How crystal parser/semantics works? What assembler do crystal use? How concurrency works internally?
All these stuff is almost a black box for most of us :(
Please, we need more stuff like this Crystal Internals post
Yeah, we have the code, but a Crystal Internals guide would be a nice help for us to continue this awesome language you created.
Ref: Please see Elias comments here
> ). And people have hope that someone from Manas is going to do that, but that's not true, simply because they don't have time (at least now) and they don't have the knowledge of the compiler (only I have it, because I've been coding it for the past four years).
Sorry but I'm worrying about this,Where is the confidence behind all these crystal collaborators in bountysource? What they are contributing on? :(
Please, I still think Manas is a great company, but if they don't have the knowledge or time can we figure out how to fix this ;-)
While I imagine this is somewhat contentious, I'd say that compilers have improved to the point where lacking types isn't really an advantage anymore. I am unaware of any new language in development that is dynamically typed, Crystal as a particularly poignant example.
These days I'm spending a lot of time in Kotlin (recreational), and I find it a joy to work with.
I’ve been using your book as a guide to make a Lisp in Crystal and am very happy that inheritance has popped up just in time for me to think about protocols and types!
Hopefully I can get the interpreter working well enough to translate it to bytecode as that comes out.
There's <code>IO#read_bytes</code> which allows you to specify a type and "byte format" (endian-ness).
No idea if it's any faster though.
:) I was going to comment that here, thanks /u/nirvdrum ! Also nice to see it's still going, I hadn't heard of the SubtrateVM progress in a while so was fearing it hit some sort of dead end. Might edit that in :)
Also, when you're in the market for CLI tools you could give crystal a shot. Cross compilation, no need to have something installed + startup time. With bigger CLI tools (just ask sferik about t) the startup time can get troublesome even on CRuby.
https://crystal-lang.org/docs/syntax_and_semantics/macros/hooks.html does not mention the finished
hook:
class Abc macro finished def self.hi puts "Hello" end end end
Abc.hi
The above will print <code>Hello</code>. You could use this to for example implement proper JSON mappings (with functioning subclassing and all).
In Crystal.
First part:
input = File.read("input.txt") count = input.each_line.count do |line| a, b, c = line.split.map(&.to_i) (a + b > c) && (a + c > b) && (b + c > a) end puts count
Second part:
input = File.read("input.txt") count = input.each_line.each_slice(3).sum do |slice| slice.map(&.split.map(&.to_i)).transpose.count do |(a, b, c)| (a + b > c) && (a + c > b) && (b + c > a) end end puts count
I have, but not a PHP-based one. I do have Node & npm installed via nvm and working properly. Got Webpack projects working like they should (except for the live reload / hot code push part of it, due to inotify feature is missing). Also have Gulp projects working like they should (except for gulp.watch
due to inotify feature is missing).
For back-end programming I use Crystal, and the compiler works fine for development but any releases would of course be compiled natively.
The LAMP stack should be able to run, as long as you're using pre-compiled binaries and not building from source.
You might be interested in Crystal, which has the same syntax and stdlib as Ruby but compiled. I've been porting over some of my Ruby libraries so I can easily switch between both languages and have the same tools. Ruby is great for quick-and-dirty scripting, but if you need native performance, a strong Type System, ability to ship a single binary, there's Crystal. If you already know Ruby, learning Crystal is super easy.
I used @link
originally, because the hello world program did. However, it seems I recieved an error that I should use @@link
when using self.send
. After removing them, my code runs fine. Thank you.
cc: /u/valbaca
> Is there a place I can get my code reviewed
We do have r/codereview, and I assume some other developer-focused subreddit allows it (read the rules). I am not familiar with this so I won't comment on the quality of such reviews.
Remember, code reviews take time. At least ones done properly, you are asking for (potentially) hours of people's time to look and comment on your code. The best type of feedback would come from someone you know with capabilities you trust. If you know a developer IRL, then that would be the perfect person to check your code.
> well for best practices and standards?
Many languages and frameworks do have their own guidelines for how that code should be written. An excellent example is [Kotlin's coding convention}(https://kotlinlang.org/docs/reference/coding-conventions.html) and Crystal's coding style. Another way of getting hints at what is correct is by looking at official guides and documentation of the language or framework. Assume that what is written in those guides to be correct.
I don't know what language you are programming in, but most have official guidelines you should use. Like Java, some might not have such a guideline, but then we have wildly accepted guidelines, like the one from Google.
Most languages have a linter you can use to help you out.
For best practices and standards of using a language, you can look at the official documentation and guides. It is hard to say specifically what to look for, as some frameworks might have different approaches than others. If that is the case, then you might want to check out official forums or subreddits for that technology.
That's my understanding, too, on the HM question. Looks like they use Boehm for GC right now., but I don't know about plans on that. GC would have been a good question.
I've been using JSON::Serializable -- creating a class with known mappings, and then calling .from_json
.
Another option is to use the JSON::Any#as_*
methods on each field. JSON::Any docs here.
Not sure of how to convert it into a typed Hash.
Might want to update https://github.com/sstadick/lapper.cr/blob/master/shard.yml#L2 to match latest release.
You could probably replace https://github.com/sstadick/lapper.cr/blob/master/src/lapper.cr#L120-L125 with https://crystal-lang.org/api/master/Enumerable.html#max_by(&block:T-%3EU)forallU-instance-method
Also little shortcut: lapper.find(15, 20)[0]?.should eq(nil)
could do lapper.find(15, 20)[0]?.should be_nil
.
Try with Dir.glob("*", match_hidden: true)
If you look at the method definition, the first arg is *patterns
which will match all positional arguments. To be able to specify the arg match_hidden
you need to call it using a named arg.
See https://crystal-lang.org/reference/syntax_and_semantics/default_values_named_arguments_splats_tuples_and_overloading.html for more info on that!
I didn’t use OOP in PHP on all projects except Laravel, it’s only it start to make sense when I learn Crystal and Ruby programming because it has concise syntax and OOP make it useful for writing cleaner code:
https://crystal-lang.org/docs/syntax_and_semantics/everything_is_an_object.html
Even complex as using Mortal Kombat as an example:
https://github.com/crystal-community/crystal-patterns/blob/master/README.md
It’s useful to deal with mental block or didn’t understood why PHP syntax grew more complex, it’s probably some parts was inspire from Ruby.
Ah yes I've heard good things about gtk and the relatively nice integration with 'modern' languages. I remember reading a blog post about someone writing a gui using Crystal and gtk which looked a lot nicer than usual methods of assembling native guis.
Agreed, an open source sublime text would be pretty awesome. Sublime has to be one of the most responsive and well designed gui edtors I've tried.
In case you didn't know, there is also property!
https://crystal-lang.org/api/0.25.1/Object.html#property!(*names)-macro that comes handy on lazy initialized properties. But I encourage to avoid lazy initialized properties when possible.
But zip
traverses both array in tandem. What you want is Array#product:
https://play.crystal-lang.org/#/r/4h5c
In your case:
st_from_site.product(st_from_oldr) do |s, ss|
s.last_dump = ss.last_dump if s.name == ss.name && s.id == ss.id
end
stations.concat(st_from_site)
I guess some people see different advantages. e.g I wanted to create a cli for developers at work, I could use bash / python / ruby and be affected by different shells / versions that run the code and dev local envs that I did not configure. A binary is the way to go in that case, and Go simply makes it accessible.
Python never let me down either, it's still my go-to language when I want to be productive and happy :)
But you have to choose the right tool for the task when you can.
About concurrency - Yep, google tends to do that, but you see this paradigm starting to spread and other lanaugages use something very similar. And interesting one is Crystal Lang. I highly recommend it! All the good Go stuff combined with a Ruby syntax (and even better performance than Go they claim). It's in very early stages but deff something to watch.
Crystal has "fibers" which is very much like Go routines.
The playground show the values after an actual execution. I think you don't want that. In some way the crystal type inference is more like a symbolic execution performed upon an invocation is reached.
There are two ways it might be helpful to you:
# file: foo.cr
def behaviour(a)
a + a
end
res = behaviour(2)
$ crystal tool types foo.cr | grep res
res : Int32
but you need at least one invocation in the main body. Otherwise the behaviour function is never compiled.
I strongly suggest you use <code>JSON.mapping</code> so that you can use to_json
on the character class directly.
Don't worry about a memory leak, it's the job of the GC to cleanup the Character
instances when they are no longer used.
This really bit me in the ass when consuming json in javascript generated by PHP.
These days I like Crystal's middle ground. I shouldn't have to tell the compiler that "a=5" means integer. Crystal only complains when you trying to operate on incompatible types (like add a list to a string) or perform an operation on Nil.
And you might find using C with Crystal to be nice: • https://crystal-lang.org/docs/syntax_and_semantics/c_bindings/ • http://www.crystalforrubyists.com/book/book.html (scroll to bottom section "C Bindings")
Haha! I'm surprised about Ruby though, come on! Isn't that kinda like Apple if they were a programming language? Stylish, smooth, clean, pretty. It's like it says on one of the Ruby projects' tin, you want to put it in your pipe and smoke it.
Yeah, the Achille's hell is no doubt performance. Seems like it's an inherent problem tough to solve too, just like with Python and the GAC, but hmm, I'm at least wishing the Crystal guys good luck! :)
It is crystal. The original compiler was in ruby and I remember reading a while back that they found it easy rewriting the compiler because of the similarities in syntax. https://crystal-lang.org/2013/11/14/good-bye-ruby-thursday.html This discusses the transition which happened a while back.
Hi!
Check https://crystal-lang.org/api/0.21.1/HTTP/Params/Builder.html so you don't need to https://github.com/sb89/crystal-darksky/blob/master/src/darksky/client.cr#L15
In JSON.mapping, you can use field: Float32?
instead of field: {type: Float32, nilable: true}
In terms of performance, I was able to reduce the computational time from 1m57.812s to 0m30.203s (25.6% of the original time) on my 2.8 GHz 16 GB memory machine simply by changing each 'class' to a 'struct'. The difference is that structs are allocated on the stack in Crystal. This is a common performance optimization in Crystal (https://crystal-lang.org/docs/guides/performance.html). For comparison, the Go code, also listed on the site, ran on my machine in 1m22.466s. I think that with the use of structs instead of classes, Crystal does run very similar to C speeds. Otherwise, I really enjoyed this article. The author compares several other languages with the same benchmark (see http://www.eccentricdevelopments.com/programming-language-co...). It would be interesting to see D-lang in a future comparison.
I don't believe I said "Ruby with performance". What I did say was "If you need raw native performance, but still want to keep Ruby syntax, we now have Crystal as an option." Crystal does have Ruby-like syntax, meaning it has similar (but not equivalent) syntax to Ruby. This is a fact which anyone can verify for themselves.
The only reason Python has better scientific/math performance is because of Num.py and how they pushed the majority of their code down into C functions, which made the code less accessible/readable. If you need raw native performance, but still want to keep Ruby syntax, we now have Crystal.
Crystal has quite a few interesting web frameworks like Amber and Kemal. It's obviously very ruby like, having been inspired by ruby, but definitely worth a look if you're thinking about trying a compiled language / framework.
This is a cool article, but there are two things here that confused me a bit:
ruby
with vim
is my zen.
Crystal is my new favorite though it's not a mature language yet. It's a spiritual successor to Ruby with a type system and a modern concurrency model.
Since this is a programming web site here are a couple of programming languages that need support.
Crystal: https://crystal-lang.org/
Seed7: https://github.com/ThomasMertes/seed7
Odin: https://odin-lang.org/
You may want to keep an eye on Crystal. It has all of the benefits of Go, with Ruby syntax and core classes, macros, Generics, etc. It just doesn't have the talent pool that Go or Ruby has, but if you know Ruby you can easily learn Crystal.
Are you aware of https://crystal-lang.org/reference/guides/static_linking.html ?
The limitations (or hurdles) to static linking are solely based on libc. On Mac, you can't statically link libc at all. On Linux, the most commonly used glibc doesn't work well with static linking either. But you can perfectly fine compile fully statically linked Crystal binaries on Linux by linking against musl-libc. This works really well and many Crystal applications are distributed as statically linked executables.
Go avoids that by implementing their standard library without relying on libc. That's a huge effort to build on your own. And the downside is it complicates interoperability with C libraries.
I can't believe I'm not seeing Crystal mentioned here. Looks and feels more like Ruby than Python but I actually am faster at writing Crystal than Python now.
Some actual code I run in prod https://github.com/dscottboggs/dynamic-dns/blob/master/src/run.cr
Fair enough. Did you actually benchmark the two approaches and notice a perf difference? LLVM is pretty good in terms of optimization so I wouldn't be surprised if they're the same.
There's also https://crystal-lang.org/reference/syntax_and_semantics/annotations/built_in_annotations.html#alwaysinline which could be useful in some cases.
It has OptionParser and compiles to a binary, plus there are a handful of other CLI framework libraries, so no reason it can't be used.
Wish them luck, but porting it to Crystal would have been easier due to how similar the languages are, and still provide all of the benefits of Go (single binary, native performance, concurrency, types, etc).
My apologies, I didn't see the rest of the file - I wonder why the (docs)[https://crystal-lang.org/api/1.0.0/Signal.html] mention fibers then
>Signals are dispatched to the event loop and later processed in a dedicated fiber. Some received signals may never be processed when the program terminates.
I’m of the opinion that most of these kinds of tech are cyclical in terms of popularity. There are other newer projects which are largely influenced by ruby too. Crystal is one that I’ve been keeping some tabs on over the past few years.
> They set Java up to build using a build tool but didn't do same for Crystal
As far as I understand the Crystal compiler - in contrast to GCC or javac - includes a full build system (see https://crystal-lang.org/reference/using_the_compiler/index.html#crystal-build). And since it uses LLVM I assume it should be able to automatically handle multiple cores if present. Some of the compiler phases might be able to run in parallel, some not; but I would expect the integrated build system to automatically take care of that.
I don't think that Zig is well-known, even in this sub-reddit (which is the only place that I've ever even seen it mentioned). It seems to be a one-man band (Andrew Kelley), and is still well before its 1.0 release, i.e. it's not really ready to be used to build things, unless you're willing to roll up your sleeves a bit to work on Zig itself. Its code is all open source, with a great (permissive) license, and the price is right.
However, I think you're looking for something more like Crystal, which (despite its own version number) seems a lot more mature: https://crystal-lang.org/
This looks like using crystal-imgui-sfml but linking against the "vanilla" version of libcimgui.so, rather than the one provided by crystal-imgui-sfml.
Would be glad to discuss it in some chat
> Truly static binary deployments seem to not be fully supported in Crystal just yet
I don't think this is entirely accurate. Static binaries in Crystal are possible, you just need to build the binary in an Alpine image. The reasoning is it uses musl-libc
which allows it to be statically linked, as opposed to gnu-libc
.
See https://crystal-lang.org/2020/02/02/alpine-based-docker-images.html
\cc \u\myringotomy
Crystal (https://crystal-lang.org/) has demonstrated (to me, at least) that you really can have the unceremonious scripting-language feel in a statically typed language with type inference. There's no good reason to create dynamic or gradually typed languages anymore.
Fair enough. I think you would be better off making your own Log::Backend specific to fluentd
. Then anyone who also uses it could just plug in the backend and have everything just work as opposed to essentially maintaining your own implementation of what the stdlib does and requiring the user to use two separate implementations.
Alternatively, you can define a custom Log::Formatter to support converting the Log::Entry
into some (more readable) format.
I came here after seeing that they sponsor the Crystal project. The fact that they're pushing hard on this language makes me want to dive into it as well. It's the equivalent of DHH developing Ruby/Rails at Basecamp.
This is massive for the language and the long term support of it.
It's a bit weird, yeah. Maybe because our domain is crystal-lang.org and our GH org is crystal-lang? But then their source package is crystal
...
Well maybe the answer is the same as for anything else in Debian, it's policy :D
The secret sauce in this coding session is made of two ingredients * Crystal generics * Functions as first-class citizens
Crystal's implementation is based on libcrypto. Crystal allows for easily writing c-bindings in order to use pre-existing libraries in your Crystal code.
I also did two quick benchmarks that do not seem to indicate Ruby is faster in this regard. If you have evidence otherwise, I'd create an issue for it.
Ruby code:
require 'digest'
Digest::SHA2.hexdigest 'dsfSDFHG(GWFGSDFgsudfgdsufgSWE&*FGWEFgsf7(SGTD&8f5sF'
Results:
$ time ruby test.rb
real 0m0.085s user 0m0.061s sys 0m0.021s $ time ruby test.rb
real 0m0.090s user 0m0.066s sys 0m0.022s $ time ruby test.rb
real 0m0.093s user 0m0.068s sys 0m0.022s
Crystal Code:
require "openssl"
OpenSSL::Digest.new("SHA256").update("dsfSDFHG(GWFGSDFgsudfgdsufgSWE&*FGWEFgsf7(SGTD&8f5sF").hexdigest
Results:
$ crystal build --release test.cr $ time ./test
real 0m0.068s user 0m0.004s sys 0m0.006s $ time ./test
real 0m0.010s user 0m0.005s sys 0m0.005s $ time ./test
real 0m0.010s user 0m0.005s sys 0m0.005s
Would the concurrency model of Crystal not help with IO
bound processes? Especially paired with, the experimental Multi-Threading mode. See https://crystal-lang.org/2019/09/06/parallelism-in-crystal.html.
I'd also imagine Crystal would use less memory compared to Ruby, just due to its compiled nature.
Gotcha, so in that case I'd do something like:
class Encipher def initialize(@message : String) puts "Your original message is: #{message}" end
def message : String @message.reverse end end
print "Enter your name: "
if (user_input = gets) && !user_input.blank? puts Encipher.new(user_input).message else STDERR.puts "Invalid input!" end
Using https://crystal-lang.org/api/String.html#reverse-instance-method
I'd also suggest joining the gitter channel. Would be easier than going back and forth on here.
Multithreading has already landed in the Crystal runtime, see [blog post](https://crystal-lang.org/2019/09/06/parallelism-in-crystal.html).
It's not yet 100% stable so it's hidden behind a feature flag. I don't think there's a tracking issue on GitHub for what's left to be done. /u/bcardiff knows more.
A good help would probably be to just using it experimentally to find bugs.
Windows support and parallelism were the biggest stumbling blocks to a 1.0 release. Both were kind of ignored for a long time because there wasn't anyone willing and able to do it, but now they're both progressing at a steady pace.
Have you heard of Crystal Lang? https://crystal-lang.org/
Chef is an IT tools for me. New dev joins the team, chef will create the dev machine. We also have 3rd party systems and legacy apps that we keep chef around for. Ultimately We mainly use Chef for compliance auditing (Chef inspec) and the occasional bundling of legacy apps into docker containers (Chef habitat). But I agree that it is a dying tech for developers.
I would take a look at how [delegate](https://crystal-lang.org/api/master/Object.html#delegate(*methods,toobject\)-macro) works in the stdlib.
Essentially it expands into a method like what you're doing, but uses splats to pass the arguments.
delegate :foo, to: @var # => def foo(*args, **options) @var.foo(*args, **options) end
Although I can't say what you're doing would be considered a good/best practice.
You can (since I think 0.32) set a number of worker threads that fibers will be run in. https://crystal-lang.org/2019/09/06/parallelism-in-crystal.html
Still seems sorta new and experimental. I've only played around with it a bit.
Thank you!
nanvault is a standalone tool - it is not a part of Ansible and does not depend on it to work.
So, from this point of view, there are no new dependencies to track.
Crystal is a compiled language, so you don't need to install Crystal to run nanvault binaries.
Moreover, nanvault binaries are statically linked, so you're free from other libs dependencies too.
Ah I think i see the issue.
https://github.com/oren/note/blob/master/src/note.cr#L45
Are you hitting this code? You might want to use File.expand_path with the home: true
option to resolve ~
to the home dir.
Ahh I think I see what you want to do, make the most recent entry appear at the top; in which case yea what you're doing is prob the easiest.
If I had to guess, the issue is that it'll create the file if it doesn't exist, but it does not handle creating the directory path TO that file.
So, I would try creating the directories first.
Also a few tips from glancing at your code.
crystal tool format
, and checkout the style guide.abort "Error trying to parse the config file. #{ex.message}"
which would handle writing the error to STDERR
and returning 1
exit code.File.open
to handle writing notes_file_path
, versus reading it to a string just to write it back to a file.Something like:
record Config, note_location : String do include JSON::Serializable end
...
con = Config.from_json File.read(@config_file_path)
con.note_location
EDIT: Add example of writing notes
# You can just open the file in append mode File.open(@notes_file_path, "a") do |notes_file| notes_file << Time.local.to_s("%Y-%m-%d") if @date notes_file << "\n\n" end
A very nice and informative read.
But i somehow feel that it will have been easier on the author, to move the code from Python to Crystal ( https://crystal-lang.org/ ). Given the more familiar structural syntax and similar performance ( as Go ).
The whole generics, try/cache and other issues the author ran into, are not issues with Crystal.
I started a smallish app using Kemal, and it felt great, to be honest. It felt like writing Ruby but much... safer? It's also much cleaner than using Sorbet. I have a lot of hope for Crystal, but it's just not quite there yet, unfortunately.
According to the official docs, there will be breaking changes to the API before hitting 1.0. For anything beyond a few scripts, that's a big no for me. Also, take a dive into the issue trackers for any 3rd party libs you think you might use; the community support just isn't quite there yet. If you're banking on using a lib for critical stuff like auth and an ORM, you're really playing with fire. What if your auth lib sees that v0.5 has some huge API change that requires a partial rewrite, then decides it's not worth the maintenance effort?
I ended up doing a rewrite in Go. Go is honestly fantastic once you get into the right mindset, and I would very highly recommend it. That said, I'm subscribed here to keep tabs on the project, and I get excited every time I see Crystal mentioned in the wild. If more Ruby devs catch wind of this, all it'd take is a big corporate sponsorship (Salesforce? Shopify?) to really get the ball rolling. In the meantime, I'll keep contributing my $5 per month and waiting for good news.
In Crystal, types are non-nilable and null references will be caught at compile time.
https://crystal-lang.org/2013/07/13/null-pointer-exception.h...
I certainly recognize that many bugs in Ruby programs announce themselves as NoMethodError: undefined method '' for nil:NilClass
. So to be able to catch that before releasing code is a very welcoming addition in my opinion.
>but I could be wrong.
You're very wrong :) `{{` and `}}` are delimiters for macro expressions.
See https://crystal-lang.org/reference/syntax_and_semantics/macros.html
Solution in Crystal
Part 1 scored me a leaderboard place (*78)
Lost some time on part 2 because I wasn't quite sure how to approach the base array in which I overwrite pixels. I iterate through the layers in reverse and write any black or white pixel.
Also, the first time I submitted part 2 I submitted the actual pixel values flattened and joined together instead of printing out the actual image, and then when I printed the image it was too difficult to see the letters, so I replaced 0 with space and 1 with #
require "benchmark"
WIDTH = 25 HEIGHT = 6 DAY = PROGRAM_NAME.match(/aoc\d{2}/).not_nil![0] INPUT = File.read_lines("#{DAY}.txt").join.chars .map(&.to_i).in_groups_of(WIDTH * HEIGHT).map(&.in_groups_of(WIDTH))
def part1 fewest_zero = INPUT.min_by { |layer| layer.flatten.count(0) }.flatten fewest_zero.count(1) * fewest_zero.count(2) end
def part2 image = INPUT.last
INPUT.reverse.each { |layer| (0...layer.size).each { |y| (0...layer[y].size).each { |x| color = layer[y][x] next if color == 2 image[y][x] = color.not_nil! } } }
image end
puts Benchmark.realtime { puts "Part 1 #{part1}" }.total_milliseconds puts Benchmark.realtime { puts "Part 2" part2.each { |line| puts line.join.gsub("0", " ").gsub("1", "#") } }.total_milliseconds
Solution in Crystal
Runs pretty quick, so I didn't bother changing part 2 (yet). Biggest issue with this puzzle was, as always, reading comprehension!
require "benchmark"
DAY = PROGRAM_NAME.match(/aoc\d{2}/).not_nil![0] INPUT = File.read_lines("#{DAY}.txt").join.split(",").map(&.to_i) OUTPUT = 19690720 # Output for part 2
def solve(noun, verb) arr = INPUT.dup # For bruteforce re-use in part 2 i, arr[1], arr[2] = 0, noun, verb until arr[i] == 99 case arr[i] when 1 then arr[arr[i + 3]] = arr[arr[i + 1]] + arr[arr[i + 2]] when 2 then arr[arr[i + 3]] = arr[arr[i + 1]] * arr[arr[i + 2]] end i += 4 end arr[0] end
def part2 # Could be reversed instead of brute forced (0..99).each { |noun| (0..99).each { |verb| return "#{noun}#{verb}" if solve(noun, verb) == OUTPUT } } end
puts Benchmark.realtime { puts "Part 1 #{solve(12, 2)}" }.total_milliseconds puts Benchmark.realtime { puts "Part 2 #{part2}" }.total_milliseconds
Hey u/pynix, excellent question. If object allocation is a bottleneck in your application, then struct seems to be the way to go - see Use structs when possible.
That said, I really suggest you profile your application with both, as passing objects by reference can sometimes lead to higher performance. It really depends on the memory allocation patterns showing in your application.
I also think we don't have enough benchmark on struct vs class when it comes to concurrent applications and passing objects over channels - something I'd like to look into in the future.
This PR lead to a pretty extensive conversation on the topic.
I hit a dead link from the Windows installation instructions it gives you a link for an installation on Ubuntu and just shows - puts " Page not found" this is the link https://crystal-lang.org/installation/on_wsl/on_ubuntu