Crystal: the programming language(crystal-lang.org)
crystal-lang.org
Crystal: the programming language
http://crystal-lang.org/
9 comments
Curious, I've been hearing a lot lately about functional languages and immutability and wasn't quite sure how it worked. I agree with it in premise but it seems like all these immutable data structures introduce massive overhead.
What is going on behind the scenes when I modify a single value in an array with 10k members? Surely it's not going to create an entirely new array.
What is going on behind the scenes when I modify a single value in an array with 10k members? Surely it's not going to create an entirely new array.
It might do that wildly inefficient thing...
Or, you might do something where you have a list of pointers, and you point at a different value instead of mutating an existing value.
I haven't dug into the details of how immutable data structures can be made to work efficiently, but part of the charm is that in many cases you don't mutate the array at all. What I mean is, there are certain behaviors around mutation that programmers do because they can.
When you take away the ability to mutate data, you design differently and without side effects. All of a sudden testing becomes easier, faster, cheaper for large parts of your codebase. You have simpler solutions that are potentially easier to reason about because the complex (and sometimes elegant) solutions aren't so readily available.
A few talks that are around this style of thinking:
https://www.destroyallsoftware.com/talks/boundaries
https://www.youtube.com/watch?v=WpkDN78P884
https://www.youtube.com/watch?v=tq5SQ4W3gRI
http://www.infoq.com/presentations/Simple-Made-Easy
Boundaries are good, values are good, simple things that work together are good. The more we can take the good parts and form them together into a cohesive language/framework/platform, the better our software will be.
Or, you might do something where you have a list of pointers, and you point at a different value instead of mutating an existing value.
I haven't dug into the details of how immutable data structures can be made to work efficiently, but part of the charm is that in many cases you don't mutate the array at all. What I mean is, there are certain behaviors around mutation that programmers do because they can.
When you take away the ability to mutate data, you design differently and without side effects. All of a sudden testing becomes easier, faster, cheaper for large parts of your codebase. You have simpler solutions that are potentially easier to reason about because the complex (and sometimes elegant) solutions aren't so readily available.
A few talks that are around this style of thinking:
https://www.destroyallsoftware.com/talks/boundaries
https://www.youtube.com/watch?v=WpkDN78P884
https://www.youtube.com/watch?v=tq5SQ4W3gRI
http://www.infoq.com/presentations/Simple-Made-Easy
Boundaries are good, values are good, simple things that work together are good. The more we can take the good parts and form them together into a cohesive language/framework/platform, the better our software will be.
This book is more or less the definitive book on functional persistent data structures. More about how to design and reason about them, then a collection book.
http://www.amazon.com/Purely-Functional-Structures-Chris-Oka...
http://www.amazon.com/Purely-Functional-Structures-Chris-Oka...
> Curious, I've been hearing a lot lately about functional languages and immutability and wasn't quite sure how it worked. I agree with it in premise but it seems like all these immutable data structures introduce massive overhead.
There is some seemingly inherent overhead for certain data structures. On the other hand it allows for structural sharing, and plays more nicely with concurrency and whatnot. Suffice it to say that you'd be wise to design your immutable (persistent, specifically) data structures very differently to how you would design your regular imperative data structures. There was a famous PhD dissertation - now a book - on the topic. You'll find it easily enough if you search for it.
Yes, immutable data structures seem very inefficient. But they're implemented in a more clever way than to just take regular imperative data structures and copying for every "update" instead of directly mutating.
> What is going on behind the scenes when I modify a single value in an array with 10k members? Surely it's not going to create an entirely new array.
It would be unwise to use a huge array (in the usual sense - contiguous memory) like that to begin with. You'd probably have an "array" that is more in the shape of a tree, which facilitates more efficient "updates".
There is some seemingly inherent overhead for certain data structures. On the other hand it allows for structural sharing, and plays more nicely with concurrency and whatnot. Suffice it to say that you'd be wise to design your immutable (persistent, specifically) data structures very differently to how you would design your regular imperative data structures. There was a famous PhD dissertation - now a book - on the topic. You'll find it easily enough if you search for it.
Yes, immutable data structures seem very inefficient. But they're implemented in a more clever way than to just take regular imperative data structures and copying for every "update" instead of directly mutating.
> What is going on behind the scenes when I modify a single value in an array with 10k members? Surely it's not going to create an entirely new array.
It would be unwise to use a huge array (in the usual sense - contiguous memory) like that to begin with. You'd probably have an "array" that is more in the shape of a tree, which facilitates more efficient "updates".
I may be perceiving this wrong, but it appears to me that in more recently newly created languages lexical scoping and explicit variable declaration are conspicuously absent. In the face of these features' positive effects on software quality and maintainability, i have to suspect that their lack is usually a conscious decision.
However, probably due to my inexperience in creating programming languages, i cannot think of reasons for this kind of decisions.
What could these be?
However, probably due to my inexperience in creating programming languages, i cannot think of reasons for this kind of decisions.
What could these be?
I'm no language designer either, but I would guess that since Crystal wants to be 100% type inferred, they feel that having to type "var" or "let" is just boilerplate.
Even in type inferred languages they serve some use, namely in avoiding mis-typed variable names. Languages which require "var" make a distinction between the intent of declaring a new variable vs setting the value of an existing variable, and so are able to catch instances where the programmer tries to set a non-existent variable.
Or more tersely use := and = to distinguish them.
That has nothing to do with the scoping. There's no way to know whether "left = right" means "Set 'left' to 'right'" or "Create a new variable 'left', with value 'right'".
How are they different? Both produce the same end result, Python manages this syntax just fine.
"Just fine" is papering over the fact that people get tripped up by this in Python all the time – sometimes you need to use the `global` or `nonlocal` statements to resolve the ambiguity.
https://docs.python.org/3/reference/simple_stmts.html#global
https://docs.python.org/3/reference/simple_stmts.html#nonloc...
Classic example: http://stackoverflow.com/questions/9264763/unboundlocalerror...
If you search for UnboundLocalError on StackOverflow, there are 918 results. Not all of them are due to this particular scoping ambiguity, but many of them are.
https://docs.python.org/3/reference/simple_stmts.html#global
https://docs.python.org/3/reference/simple_stmts.html#nonloc...
Classic example: http://stackoverflow.com/questions/9264763/unboundlocalerror...
If you search for UnboundLocalError on StackOverflow, there are 918 results. Not all of them are due to this particular scoping ambiguity, but many of them are.
It's a mistake even in Python. It makes typos harder to catch. And a visible distinction between variables that change and values that don't makes code much easier to reason about.
> In the face of these features' positive effects on software quality and maintainability
are you sure about this for explicit variable declaration? In my experience the problem is more with autovivification than with declaration-is-initialization.
are you sure about this for explicit variable declaration? In my experience the problem is more with autovivification than with declaration-is-initialization.
I can't think of any recently-designed languages that do not have lexical scoping - can you?
I'm not sure I can think of any languages at all that have dynamic scoping since the early lisps.
I'm not sure I can think of any languages at all that have dynamic scoping since the early lisps.
Features like Scala's implicit parameters could be argued to be a kind of "dynamic scope". True, the language is lexically scoped and most code is written expecting that, but it does allow you to "opt out" of this scoping mechanism and look for values to be specified in the environment.
Perl my/our/local is the most unusual scoping I know of[1]. But still lexical, except maybe local which is more like an alias?
[1] http://www.perlmonks.org/?node_id=66677
[1] http://www.perlmonks.org/?node_id=66677
my is lexical, our is global, local is dynamic.
I'll premptively add a bit of precision before a pedant comes along: my is lexical all the way; our defines a lexical binding over a global variable, and local defines a dynamic binding (of lexical extent) over a global.
Are you sure the pedant hasn't already arrived? ;-)
The only ones I can think of are Python and Javascript, both were created in the 90's.
Python and JavaScript both have lexical scoping - e.g. http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.
Ah my mistake then, I must be misunderstanding what lexical scoping is.
One mans maintainability is another mans mess.
I am excited to see new programming languages like this. I can name 100 duck typed, interpreted, GC'd languages, but only half a dozen native compilers for modern languages. Native binaries are much easier to deploy on consumer's desktops than bytecode or source code requiring >50MB VMs, and the code tends to be much more rigid and rigorous with a statically typed language like this.
I haven't downloaded the compiler yet, but here are a few things I like after reading the documentation.
- The C bindings are nice and simple in Crystal, with full support for structures and data types,
- "Globally named" symbols are a really great idea, especially in native binary when compiled to Int32's,
- OOP support seems polished with full support for encapsulation,
- Basic control structures and scope are also polished and familiar, while leaving beind the nasty parts from Ruby (i.e. `for do` vs `for`, Matz's regret for `do ... while`, etc)
- --hierarchy. Why haven't I seen a compiler support this by now?
A final point: "Everything is an object" and C-like efficiency seems paradoxical, but I'll look more into this. Objects may be abstracted by the compiler, but once compiled behave like any ole' statically typed system.
I haven't downloaded the compiler yet, but here are a few things I like after reading the documentation.
- The C bindings are nice and simple in Crystal, with full support for structures and data types,
- "Globally named" symbols are a really great idea, especially in native binary when compiled to Int32's,
- OOP support seems polished with full support for encapsulation,
- Basic control structures and scope are also polished and familiar, while leaving beind the nasty parts from Ruby (i.e. `for do` vs `for`, Matz's regret for `do ... while`, etc)
- --hierarchy. Why haven't I seen a compiler support this by now?
A final point: "Everything is an object" and C-like efficiency seems paradoxical, but I'll look more into this. Objects may be abstracted by the compiler, but once compiled behave like any ole' statically typed system.
>Matz's regret for `do ... while`
Huh? Do you mean http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/...? It's still there: http://crystal-lang.org/docs/syntax_and_semantics/while.html
Edit: Ah, the behavior of the while modifier is different in Crystal.
Huh? Do you mean http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/...? It's still there: http://crystal-lang.org/docs/syntax_and_semantics/while.html
Edit: Ah, the behavior of the while modifier is different in Crystal.
I was referring to the veil of deprecation over `do end while` by Matz's comment that you've linked, but as long as Crystal endorses it, is it fine with me.
We actually started by copying ruby's syntax and semantic, including the `do end while`. But a long time ago we started to diverge from it. We are also not sure about this "feature" and we still have time to remove it from the language :-) . It's true that a simple `while ... break if ... end` is enough.
Edit: I also misunderstood the comment. In Crystal `exp while cond` and `begin exp end while cond` are the same.
Edit: I also misunderstood the comment. In Crystal `exp while cond` and `begin exp end while cond` are the same.
The example sieve does a bit of extra work. You can start at
Nice work.
candidate**2
instead of candidate*2
since the composite `2` has already been removed in a previous iteration.Nice work.
[deleted]
Already has GitHub color coding?
https://github.com/manastech/crystal
https://github.com/manastech/crystal
The first lexer was added over a year ago: https://github.com/github/linguist/pull/678
Are there any bench marks comparing it to ruby, c or even mruby?
Yes. There are some here:
https://github.com/kostya/benchmarks
Here's another one:
https://github.com/nsf/pnoise
And then in the samples directory ( https://github.com/manastech/crystal/tree/master/samples ) there are some more but without time results (but you can try them yourself).
https://github.com/kostya/benchmarks
Here's another one:
https://github.com/nsf/pnoise
And then in the samples directory ( https://github.com/manastech/crystal/tree/master/samples ) there are some more but without time results (but you can try them yourself).
Groovy : Java :: Crystal : C ?
Don't we already have more than enough programming languages? I looked through the intro and this language introduces nothing new. Your time would have been better wasted on building a framework for an already established language. Sorry for putting you down, consider it tough love
A man needs to own up to his mistake, i found all your points to be valid, and i hope that the developer of the language to excuse my rushed judgment. It's always good to know that there are people here that could set me straight when i'm mistaken, and in a polite way too. My apologies again
Your comment was actually pretty good because it spawned other very positive comments. We really like them all :-)
Not even close. There is an incredible amount of room for innovation and research in programming languages. You do not have to learn this or any of them and can continue to program in whichever language is at the peak of commercial success at the moment.
But it is important that we continue to try new things and make progress in this area.
Unfortunately this particular project does not seem to push many boundaries.
But it is important that we continue to try new things and make progress in this area.
Unfortunately this particular project does not seem to push many boundaries.
> Don't we already have more than enough programming languages?
No.
> I looked through the intro and this language introduces nothing new.
Its individual features aren't unique. The combination of them in one language seems to be somewhat new. What language do you see that it is redundant with?
No.
> I looked through the intro and this language introduces nothing new.
Its individual features aren't unique. The combination of them in one language seems to be somewhat new. What language do you see that it is redundant with?
Some people build programming languages as a learning exercise.
EDIT: And actually, having looked at it, this is no learning exercise, but a pretty cool language. There are few languages with type inference, high-level syntax, and compile to (supposedly) efficient binaries.
EDIT: And actually, having looked at it, this is no learning exercise, but a pretty cool language. There are few languages with type inference, high-level syntax, and compile to (supposedly) efficient binaries.
> Your time would have been better wasted on building a framework for an already established language
Don't we already have more than enough frameworks for established languages? :\
Don't we already have more than enough frameworks for established languages? :\
We have far more frameworks than we do languages, also there is a ton of knowledge to be gained by going through the steps of designing and implementing a programming language.
Programming languages in the modern sense are different to programming languages of, say, 20 yrs ago. If a language sits atop the JVM or generates Javascript, it's a "new programming language" in the modern sense but probably wasn't considered one previously. And nowadays, a "programming language" needs a visual IDE or plugin, rather than just a syntax, to be considered more than just a toy.
In a thread on hacker news recently someone brought up the "value of art":
https://news.ycombinator.com/item?id=8612359
I agree. We have tons of programming languages but if anything, this can exist as "Art" or study.
https://news.ycombinator.com/item?id=8612359
I agree. We have tons of programming languages but if anything, this can exist as "Art" or study.
As a picky individual, I prefer this variation of languages over a few but established ones. It takes an hour to fully learn another new programming language, and it adds more excitement and comfort to programming.
Even if it were just for the grammar definition and the fun, it would not be wasted time...
Swift, Kotlin, and Scala seem to be the only significant languages to get both features pretty close to what I'd want. Otherwise, I don't see much in the language space that scratches that itch.
Those three languages seem to be the closest to getting "the future" right when it comes to the "next generation" of languages - functional, object oriented, type checked and compiled languages with a bit of dynamic checking/inference for programmer convenience. Other languages seem to be too much in other particular directions to get the benefit of different styles where it makes sense.
I had high hopes for Mirah, but it hasn't really evolved the way I'd hoped.
I don't know if my notion for a language is the right direction for Crystal, but I'd love it if someone came along and made my "perfect language" for me. It'd be one less thing to build myself.