-
-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add symbols and tuples concept and exercise #685
Changes from 6 commits
7d72c0e
1c3f95b
72d01f5
cdf9dac
138cb04
9787f6c
7cec5cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"blurb": "Symbol represent a unique identifier through the program, which is created at compile time", | ||
"authors": ["meatball133"], | ||
"contributors": [] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{% $symbol %} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,44 @@ | ||||||
# About | ||||||
|
||||||
[Symbols][symbols] are named identifiers that can be used to refer to a value. | ||||||
Symbols are created through a symbol literal, which is by prefixing a name with a `:` character, e.g. `:foo`. | ||||||
They also allow for being written with quotes, e.g. `:"foo"`, which allows, for example, spaces in the name. | ||||||
|
||||||
```crystal | ||||||
:foo # => :foo | ||||||
:"foo boo" # => :"foo boo" | ||||||
``` | ||||||
|
||||||
Symbols are used in many places in the language, including as keys in namedtuples, to represent method names and variable names. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think this is what you intended, but I may have misunderstood. |
||||||
|
||||||
## Symbols in Crystal | ||||||
|
||||||
Symbols in Crystal is quite different from Ruby. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
In Crystal is a symbol a form of constants and is thereby is assigned at compile time. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
This means that symbols can't be created dynamically, which is possible in Ruby. | ||||||
|
||||||
Symbols in Crystal is represented as an `Int32` which makes very efficient. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
## Identifier | ||||||
|
||||||
What makes symbols different from strings is that they are identifiers, and do not represent data or text. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
This means that two symbols with the same name are always the same object. | ||||||
|
||||||
```ruby | ||||||
"foo".object_id # => 60 | ||||||
"foo".object_id # => 80 | ||||||
:foo.object_id # => 1086748 | ||||||
:foo.object_id # => 1086748 | ||||||
``` | ||||||
|
||||||
## Conversion | ||||||
|
||||||
Symbols can be converted to strings but not vice versa. | ||||||
This is because symbols are created at compile time, and strings are created at runtime. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
```crystal | ||||||
:foo.to_s # => "foo" | ||||||
``` | ||||||
|
||||||
[symbols]: https://crystal-lang.org/reference/syntax_and_semantics/literals/symbol.html | ||||||
[symbols-api]: https://crystal-lang.org/api/Symbol.html | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think this is unused |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# About | ||
|
||
[Symbols][symbols] are named identifiers that can be used to refer to a value. | ||
Symbols are created through a symbol literal, which is by prefixing a name with a `:` character, e.g. `:foo`. | ||
They also allow for being written with quotes, e.g. `:"foo"`, which allows, for example, spaces in the name. | ||
|
||
```crystal | ||
:foo # => :foo | ||
:"foo boo" # => :"foo boo" | ||
``` | ||
|
||
Symbols are used in many places in the language, including as keys in namedtuples, to represent method names and variable names. | ||
|
||
## Symbols in Crystal | ||
|
||
Symbols in Crystal is quite different from Ruby. | ||
In Crystal is a symbol a form of constants and is thereby is assigned at compile time. | ||
This means that symbols can't be created dynamically, which is possible in Ruby. | ||
|
||
Symbols in Crystal is represented as an `Int32` which makes very efficient. | ||
|
||
## Identifier | ||
|
||
What makes symbols different from strings is that they are identifiers, and do not represent data or text. | ||
This means that two symbols with the same name are always the same object. | ||
|
||
```ruby | ||
"foo".object_id # => 60 | ||
"foo".object_id # => 80 | ||
:foo.object_id # => 1086748 | ||
:foo.object_id # => 1086748 | ||
``` | ||
|
||
## Conversion | ||
|
||
Symbols can be converted to strings but not vice versa. | ||
This is because symbols are created at compile time, and strings are created at runtime. | ||
|
||
```crystal | ||
:foo.to_s # => "foo" | ||
``` | ||
|
||
[symbols]: https://crystal-lang.org/reference/syntax_and_semantics/literals/symbol.html |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[ | ||
{ | ||
"url": "https://crystal-lang.org/reference/syntax_and_semantics/literals/symbol.html", | ||
"description": "Crystal docs: Symbol" | ||
}, | ||
{ | ||
"url": "https://crystal-lang.org/api/Symbol.html", | ||
"description": "Crystal api: Symbol" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,5 @@ | ||||||
{ | ||||||
"blurb": "Tuples is a data structure which stores a fixed amount of elements. Tuples are indexable and inmutable", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
"authors": ["meatball133"], | ||||||
"contributors": [] | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{% $tuples \ $"tuples"."Tuples definition shorthand" %} |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,119 @@ | ||||||||
# Tuples | ||||||||
|
||||||||
A [tuple][tuple] is a finite ordered list of elements which is immutable. | ||||||||
Tuples requires all positions to have a fixed type this in turns means that the compiler knows what type each position is. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
The types used in a tuple can be different, but the types must be known at compile time. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
## Creating a Tuple | ||||||||
|
||||||||
Depending on if the tuples values types can be interprited under compilation, the tuple can be created in different ways. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean by this sentence. Do you mean to say that you can only create a tuple literal if the types are known at compile time? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes |
||||||||
It is also important that the types of the values match the types specified in the tuple and that the number of values match the number of types specified. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
If the values are known at compile time, the tuple can be created using the tuple literal syntax. | ||||||||
|
||||||||
```crystal | ||||||||
tuple = {1, "foo", 'c'} # Tuple(Int32, String, Char) | ||||||||
``` | ||||||||
|
||||||||
There is also possibility to create a tuple using the `Tuple` class. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
```crystal | ||||||||
tuple = Tuple(Int32, String, Char).new(1, "foo", 'c') | ||||||||
``` | ||||||||
|
||||||||
Alternatively, you can explicitly specify the type of the variable assigned to the tuple. | ||||||||
|
||||||||
```crystal | ||||||||
tuple : Tuple(Int32, String, Char) = {1, "foo", 'c'} | ||||||||
``` | ||||||||
|
||||||||
Explicitly specifying the type of the tuple can be usefull since that allows for defining that a position should hold a union type. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This means that a position can hold multiple types. | ||||||||
|
||||||||
```crystal | ||||||||
tuple : Tuple(Int32 | String, String, Char) = {1, "foo", 'c'} | ||||||||
``` | ||||||||
|
||||||||
## Conversion | ||||||||
|
||||||||
### Creating a tuple from an array | ||||||||
|
||||||||
You can create a tuple from an array using the `Tuple` class's `from` method. | ||||||||
This requires that the type of the tuple is specified. | ||||||||
|
||||||||
```crystal | ||||||||
array = [1, "foo", 'c'] | ||||||||
tuple = Tuple(Int32, String, Char).from(array) | ||||||||
``` | ||||||||
|
||||||||
### Conversion to Array | ||||||||
|
||||||||
You can convert a tuple to an array using the `to_a` method. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
```crystal | ||||||||
tuple = {1, "foo", 'c'} | ||||||||
array = tuple.to_a | ||||||||
array # => [1, "foo", 'c'] | ||||||||
``` | ||||||||
|
||||||||
### Tuples definition shorthand | ||||||||
|
||||||||
There is a shorthand for defining explicit tuple types. | ||||||||
That is by writting the types inside of the tuple literal. | ||||||||
|
||||||||
```crystal | ||||||||
tuple : {Int32, String, Char} = {1, "foo", 'c'} | ||||||||
ryanplusplus marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
``` | ||||||||
|
||||||||
## Accessing Elements | ||||||||
|
||||||||
Like arrays, tuples are zero-indexed, meaning that the first element is at index 0. | ||||||||
However, unlike arrays, the type of each element is fixed and known at compile time, therefore when indexing a tuple, the type of the element is specific to the position. | ||||||||
To access an element in a tuple, you can use the `[]` operator. | ||||||||
|
||||||||
```crystal | ||||||||
array = [1, "foo", 'c'] | ||||||||
array[0] # => 1 | ||||||||
typeof(array[0]) # => Int32 | String | Char | ||||||||
|
||||||||
tuple = {1, "foo", 'c'} | ||||||||
tuple[0] # => 1 | ||||||||
typeof(tuple[0]) # => Int32 | ||||||||
``` | ||||||||
|
||||||||
Another difference when it comes to accessing elements from arrays is that if the index is specified, then the compiler will check that the index is within the bounds of the tuple. | ||||||||
Meaning you will get a compile time error instead of a runtime error. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
```crystal | ||||||||
tuple = {1, "foo", 'c'} | ||||||||
tuple[3] | ||||||||
# => Error: index out of bounds for Tuple(Int32, String, Char) (3 not in -3..2) | ||||||||
``` | ||||||||
|
||||||||
However, if the index is stored in a variable, then the compiler will not be able to check if the index is within the bounds of the tuple at compile time and will as such give a runtime error. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
## Subtuple | ||||||||
|
||||||||
You can get a subtuple of a tuple by using the `[]` operator with a range. | ||||||||
What is returned is a new tuple with the elements from the range specified. | ||||||||
The range has to be given at compile time, since otherwise the compiler will not be able to know the types of the elements in the subtuple. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This means that the range has to be a range literal and not assigned to a variable. | ||||||||
|
||||||||
```crystal | ||||||||
tuple = {1, "foo", 'c'} | ||||||||
subtuple = tuple[0..1] # Tuple(Int32, String) | ||||||||
|
||||||||
i = 0..1 | ||||||||
tuple[i] | ||||||||
# Error: Tuple#[](Range) can only be called with range literals known at compile-time | ||||||||
``` | ||||||||
|
||||||||
## When to use a Tuple | ||||||||
|
||||||||
Tuples are useful when you want to group a fixed number of values together, where the types of the values are known at compile time. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This is because tuples require less memory and is faster than arrays due to the immutability of tuples. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
Another use case is when you want to return multiple fixed values from a method. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
This is particular helpful if the values have different types since each position in the tuple can have a different type. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
When to not use a Tuple is if a datastructure is needed that can grow or shrink in size or often needs to be modified. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
[tuple]: https://crystal-lang.org/reference/syntax_and_semantics/literals/tuple.html |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Tuples | ||
|
||
A [tuple][tuple] is a finite ordered list of elements which is immutable. | ||
Tuples requires all positions to have a fixed type this in turns means that the compiler knows what type each position is. | ||
The types used in a tuple can be different, but the types must be known at compile time. | ||
|
||
## Creating a Tuple | ||
|
||
Depending on if the tuples values types can be interprited under compilation, the tuple can be created in different ways. | ||
It is also important that the types of the values match the types specified in the tuple and that the number of values match the number of types specified. | ||
If the values are known at compile time, the tuple can be created using the tuple literal syntax. | ||
|
||
```crystal | ||
tuple = {1, "foo", 'c'} # Tuple(Int32, String, Char) | ||
``` | ||
|
||
There is also possibility to create a tuple using the `Tuple` class. | ||
|
||
```crystal | ||
tuple = Tuple(Int32, String, Char).new(1, "foo", 'c') | ||
``` | ||
|
||
Alternatively, you can explicitly specify the type of the variable assigned to the tuple. | ||
|
||
```crystal | ||
tuple : Tuple(Int32, String, Char) = {1, "foo", 'c'} | ||
``` | ||
|
||
Explicitly specifying the type of the tuple can be usefull since that allows for defining that a position should hold a union type. | ||
This means that a position can hold multiple types. | ||
|
||
```crystal | ||
tuple : Tuple(Int32 | String, String, Char) = {1, "foo", 'c'} | ||
``` | ||
|
||
## Conversion | ||
|
||
### Creating a tuple from an array | ||
|
||
You can create a tuple from an array using the `Tuple` class's `from` method. | ||
This requires that the type of the tuple is specified. | ||
|
||
```crystal | ||
array = [1, "foo", 'c'] | ||
tuple = Tuple(Int32, String, Char).from(array) | ||
``` | ||
|
||
### Conversion to Array | ||
|
||
You can convert a tuple to an array using the `to_a` method. | ||
|
||
```crystal | ||
tuple = {1, "foo", 'c'} | ||
array = tuple.to_a | ||
array # => [1, "foo", 'c'] | ||
``` | ||
|
||
## Accessing Elements | ||
|
||
Like arrays, tuples are zero-indexed, meaning that the first element is at index 0. | ||
However, unlike arrays, the type of each element is fixed and known at compile time, therefore when indexing a tuple, the type of the element is specific to the position. | ||
To access an element in a tuple, you can use the `[]` operator. | ||
|
||
```crystal | ||
array = [1, "foo", 'c'] | ||
array[0] # => 1 | ||
typeof(array[0]) # => Int32 | String | Char | ||
|
||
tuple = {1, "foo", 'c'} | ||
tuple[0] # => 1 | ||
typeof(tuple[0]) # => Int32 | ||
``` | ||
|
||
Another difference when it comes to accessing elements from arrays is that if the index is specified, then the compiler will check that the index is within the bounds of the tuple. | ||
Meaning you will get a compile time error instead of a runtime error. | ||
|
||
```crystal | ||
tuple = {1, "foo", 'c'} | ||
tuple[3] | ||
# => Error: index out of bounds for Tuple(Int32, String, Char) (3 not in -3..2) | ||
``` | ||
|
||
However, if the index is stored in a variable, then the compiler will not be able to check if the index is within the bounds of the tuple at compile time and will as such give a runtime error. | ||
|
||
## Subtuple | ||
|
||
You can get a subtuple of a tuple by using the `[]` operator with a range. | ||
What is returned is a new tuple with the elements from the range specified. | ||
The range has to be given at compile time, since otherwise the compiler will not be able to know the types of the elements in the subtuple. | ||
This means that the range has to be a range literal and not assigned to a variable. | ||
|
||
```crystal | ||
tuple = {1, "foo", 'c'} | ||
subtuple = tuple[0..1] # Tuple(Int32, String) | ||
|
||
i = 0..1 | ||
tuple[i] | ||
# Error: Tuple#[](Range) can only be called with range literals known at compile-time | ||
``` | ||
|
||
## When to use a Tuple | ||
|
||
Tuples are useful when you want to group a fixed number of values together, where the types of the values are known at compile time. | ||
This is because tuples require less memory and is faster than arrays due to the immutability of tuples. | ||
Another use case is when you want to return multiple fixed values from a method. | ||
This is particular helpful if the values have different types since each position in the tuple can have a different type. | ||
|
||
When to not use a Tuple is if a datastructure is needed that can grow or shrink in size or often needs to be modified. | ||
|
||
[tuple]: https://crystal-lang.org/reference/syntax_and_semantics/literals/tuple.html |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[ | ||
{ | ||
"url": "https://crystal-lang.org/reference/syntax_and_semantics/literals/tuple.html", | ||
"description": "Crystal docs: Array" | ||
}, | ||
{ | ||
"url": "https://crystal-lang.org/api/Tuple.html", | ||
"description": "Crystal api: Tuple" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -287,7 +287,21 @@ | |||||||||
], | ||||||||||
"prerequisites": [ | ||||||||||
"procs-blocks" | ||||||||||
] | ||||||||||
], | ||||||||||
"status": "beta" | ||||||||||
}, | ||||||||||
{ | ||||||||||
"slug": "kitchen-calculator", | ||||||||||
"name": "Kitcen Calculator", | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
"uuid": "e7250ff1-967d-4b5d-8fa8-a57fdbbe24c5", | ||||||||||
"concepts": [ | ||||||||||
"symbol", | ||||||||||
"tuples" | ||||||||||
], | ||||||||||
"prerequisites": [ | ||||||||||
"iteration" | ||||||||||
], | ||||||||||
"status": "beta" | ||||||||||
} | ||||||||||
], | ||||||||||
"practice": [ | ||||||||||
|
@@ -1576,6 +1590,16 @@ | |||||||||
"uuid": "0455ecbd-dc84-4799-b49e-bc9bf0a9fc71", | ||||||||||
"slug": "iteration", | ||||||||||
"name": "Iteration" | ||||||||||
}, | ||||||||||
{ | ||||||||||
"uuid": "a36e93cb-5ab0-4693-a6ab-ce698a3550ce", | ||||||||||
"slug": "tuples", | ||||||||||
"name": "Tuples" | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should this be singular or plural? |
||||||||||
}, | ||||||||||
{ | ||||||||||
"uuid": "268c4865-1a15-4f65-88d9-5a1bb1ba5ac4", | ||||||||||
"slug": "symbol", | ||||||||||
"name": "Symbol" | ||||||||||
} | ||||||||||
], | ||||||||||
"key_features": [ | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.