From ea1d7fde0d4143621465d0eadf1f65e6e52a4da9 Mon Sep 17 00:00:00 2001 From: Bill Tihen Date: Thu, 2 Jan 2020 21:28:27 +0100 Subject: [PATCH 1/2] add records to structs section --- syntax_and_semantics/structs.md | 62 +++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/syntax_and_semantics/structs.md b/syntax_and_semantics/structs.md index 48c5ffdc5..f61a4c5dd 100644 --- a/syntax_and_semantics/structs.md +++ b/syntax_and_semantics/structs.md @@ -1,4 +1,4 @@ -# Structs +# Structs and Records Instead of defining a type with `class` you can do so with `struct`: @@ -25,7 +25,7 @@ A struct is _always_ passed by value, even when you return `self` from the metho struct Counter def initialize(@count : Int32) end - + def plus @count += 1 self @@ -93,3 +93,61 @@ ary = [] of Point If `Point` is inherited, an array of such type should also account for the fact that other types can be inside it, so the size of each element should grow to accommodate that. That is certainly unexpected. So, non-abstract structs can't be inherited from. Abstract structs, on the other hand, will have descendants, so it is expected that an array of them will account for the possibility of having multiple types inside it. A struct can also include modules and can be generic, just like a class. + +## Records + +Records are a simplified way to create a Struct _(they have default initializer)._ + +**Record Definitions** +``` +record Foo, id : Int32, name : String +# or +record(Foo, id : Int32, name : String) +``` + +Like structs, records can also have custom behaviors - defined with: +``` +record(Foo, name : String, id : Int32) do + def to_s + puts "Foo: id: #{id}; name: #{name}" + end +end +``` + +Records can be a flexible data structure (tuples and others require a fixed data structure - without `nil`s). + +For example if you need a simple data structure that may or maynot have all the data you can define a record with the following parameters `name : String? = nil` +``` +record Foo, id : Int32, name : String? = nil do + def to_s + puts "Foo: id: #{id}; name: #{name}" + end +end +``` + +**Record Usage:** +Record assignment is done using: +``` +foo1 = Foo.new(1) +# => Foo(id: 1, name: nil) + + +foo2 = Foo.new(2, "Bar") +# => Foo(id: 2, name: "Bar") +``` + +Record usage looks like: +``` +puts "id: #{foo1.id}" +# => id: 1 +puts "name: #{foo1.name}" +# => name: +puts foo1.to_s +# => Foo: id: 1; name: +puts "id: #{foo2.id}" +# => id: 2 +puts "name: #{foo2.name}" +# => name: Bar +puts foo2.to_s +# => Foo: id: 2; name: Bar +``` From f1a4ea75c90574f45d24e303b4b351aca68fd9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Fri, 29 Jul 2022 12:03:15 +0200 Subject: [PATCH 2/2] Reduce to mention of `record` macro and refer to stdlib --- docs/syntax_and_semantics/structs.md | 65 ++++++++-------------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/docs/syntax_and_semantics/structs.md b/docs/syntax_and_semantics/structs.md index 098362b83..182ffbdd7 100644 --- a/docs/syntax_and_semantics/structs.md +++ b/docs/syntax_and_semantics/structs.md @@ -1,4 +1,4 @@ -# Structs and Records +# Structs Instead of defining a type with `class` you can do so with `struct`: @@ -96,58 +96,31 @@ A struct can also include modules and can be generic, just like a class. ## Records -Records are a simplified way to create a Struct _(they have default initializer)._ +The Crystal [Standard Library](https://crystal-lang.org/api) provides the [`record`](https://crystal-lang.org/api/toplevel.html#record(name,*properties)-macro) macro. It simplifies the definition of basic struct types with an initializer and some helper methods. -**Record Definitions** -``` -record Foo, id : Int32, name : String -# or -record(Foo, id : Int32, name : String) -``` +```crystal +record Point, x : Int32, y : Int32 -Like structs, records can also have custom behaviors - defined with: -``` -record(Foo, name : String, id : Int32) do - def to_s - puts "Foo: id: #{id}; name: #{name}" - end -end +Point.new 1, 2 # => # ``` -Records can be a flexible data structure (tuples and others require a fixed data structure - without `nil`s). +The `record` macro expands to the following struct definition: -For example if you need a simple data structure that may or maynot have all the data you can define a record with the following parameters `name : String? = nil` -``` -record Foo, id : Int32, name : String? = nil do - def to_s - puts "Foo: id: #{id}; name: #{name}" - end -end -``` +```cr +struct Point + getter x : Int32 -**Record Usage:** -Record assignment is done using: -``` -foo1 = Foo.new(1) -# => Foo(id: 1, name: nil) + getter y : Int32 + def initialize(@x : Int32, @y : Int32) + end -foo2 = Foo.new(2, "Bar") -# => Foo(id: 2, name: "Bar") -``` + def copy_with(x _x = @x, y _y = @y) + self.class.new(_x, _y) + end -Record usage looks like: -``` -puts "id: #{foo1.id}" -# => id: 1 -puts "name: #{foo1.name}" -# => name: -puts foo1.to_s -# => Foo: id: 1; name: -puts "id: #{foo2.id}" -# => id: 2 -puts "name: #{foo2.name}" -# => name: Bar -puts foo2.to_s -# => Foo: id: 2; name: Bar + def clone + self.class.new(@x.clone, @y.clone) + end +end ```