Hi Crystal community!
I working in some Crystal projects with my professors and They ask me,
Why is class_*
used for static methods in both, structs and class, Are They both static class methods?
Then I have to explain that struct MyStruct;end
is also a class typeof(MyStruct) # => Class
But, things don't keep clear, I mean:
class MyClass
class_property valor = 0
end
struct MyStruct
class_property valor = 0
end
record MyRecord do
class_property valor = 0
end
MyClass.valor # => 0
MyStruct.valor # => 0
MyRecord.valor # => 0
Would be better if exist a static
alias/macro for class_*
methods.
Just like static
in other languages as Java, C#, C++ and even TypeScript.
macro static(m)
class_{{m}}
end
class MyClass
static property valor = 0
end
struct MyStruct
static property valor = 0
end
record MyRecord do
static property valor = 0
end
p MyClass.valor # => 0
p MyStruct.valor # => 0
p MyRecord.valor # => 0
An excellent use case would be the ease to explain to Non Ruby programmers (Like my professors :sweat_smile: ) How to do static getters, setters and properties in Crystal.
class_*
implementation PR by @Sija :point_right: https://github.com/crystal-lang/crystal/pull/3658
Alias means some people will write static
, some will continue write class_
, and everybody will have to learn both syntax in order to understand somebody else code.
I like class_
more as it's how it is named in both Pascal and Ruby and imho makes more sense - it means that thing is a property of class, as opposed to members of class instance. I've never thought about it, but yes, as "everything is an object" and MyStruct.is_a? Class
it is even technically correct.
static
naming it widely used though so it would make sense too, but having both isn't good.
@konovod Thanks for your comment!
...and everybody will have to learn both syntax in order to understand somebody else code.
While I was learning Crystal I heard this so many times.
I read something similar here :point_right: https://github.com/crystal-lang/crystal/wiki/FAQ#why-are-aliases-discouraged
In this case, then I rewrite my question:
Can be class_*
replaced by static
keyword?
For now, I'm using a static
macro:
macro static(m)
class_{{m}}
end
Can be class_* replaced by static keyword?
In that case I personally prefer class_
, but that's just matter of taste. If most people prefer static
- why not.
If most people prefer static - why not.
Thanks you for your consideration :smile:
I like class_*
as it's clear that it allows property on the Class
object, but it is inconsistent with the fact that they can also be used in modules (and structs as you demonstrated before):
module MyModule
class_property value = 3
end
pp MyModule.value # => 3
For that matter I'd prefer static_*
(static_property
, static_getter
, static_setter
), so the semantic would work on class
, struct
and module
.
@bew I like static_*
too :+1:
just kidding, but MyModule.is_a? Class # => true
static
definition:
lacking in movement, action, or change, especially in a way viewed as undesirable or uninteresting.
class_property
provides ways to access class level variables via class level methods (getter self.foo
and setter self.foo=
).
Naming it static
might imply the value set to that property does not change, which it might (when using the setter part of the property).
just kidding, but聽
MyModule.is_a? Class # => true
Even Class
is a class, Object is a class, Module is a class and primitives like Int32
and others are classes.
Crystal object hierarchy is deeply inspired by Ruby. This peculiarity about everything being a class can be better described in this Stack Overflow response:
https://stackoverflow.com/questions/27648665/why-is-everything-an-instance-of-class-in-ruby
@luislavena but in Java and C# you can change things with static methods also static attributes.
Look a minimal example in Java:
public class ClassName {
public static void main(String[] args) {
ClassName2.value += 1;
System.out.println(ClassName2.value); // 1
}
}
class ClassName2 {
static int value = 0;
}
lacking in movement, action, or change, especially in a way viewed as undesirable or uninteresting.
Then, Is static like a CONSTANT?
Does crystal have static behavior available?
BTW, Thanks you for your comment! :sweat_smile:
@faustinoaq in Java, the static
keyword is used to indicate that the method exposed belongs to the class and not the instance.
But that is Java and C#, so their definition of static applies to them.
The word static to a Rubist indicates a constant: a value that doesn't change with execution/runtime. Things that are exposed at the class level (not the instance) falls better into the class definition.
In C, static means something completely different.
IMO, the languages the developers are coming from might twist their perception of static vs class on the conventions used by other languages and they might want to adapt the language to the idioms they found familiar in previous languages. We all do that :smile:
Cheers.
This issue seems interesting to me, I wish to read other opinions.
BTW, If MyModule.is_a? Class # => true
then Why I can't create a module instance? :point_right: https://crystal-lang.org/docs/syntax_and_semantics/modules.html
module
is like a "special" class
:sweat_smile:
What about global_property
, global_getter
& global_setter
?
(did you see the word "global" ? _please don't hurt me_)
In the end it's a global, namespace'd but still a global, so we could name it for what it is.
Currently, I think class_*
methods are nice, I will close this issue, if somebody want to add something, feel free to comment this issue, and maybe reopen it.
In Crystal and Ruby, everything is Object.
1
is object, "string"
is object, nil
is object, AnyClass.new
is returned as object, and even AnyClass
and AnyStruct
are all object.
In Crystal, we call these object's type 'class', that's why we provided #class
method in any object.
And these classes are instances of its metaclass which is carrying properties and methods and even recording the constructors and the class (aka base-class) information.
(If there's a suggestion of changing class_*
, I would suggest meta_*
)
And why Modules cannot be 'newed'?
Because module's metaclass doesn't has base- class. (And more, module's metaclass is itself)
Crystal's meta-model is inspired from Ruby, and you can search about meta in issues for more information.
PS. Crystal's meta-model is complicated, if anything I understood wrong, please correct me.
Most helpful comment
static
definition:class_property
provides ways to access class level variables via class level methods (getterself.foo
and setterself.foo=
).Naming it
static
might imply the value set to that property does not change, which it might (when using the setter part of the property).Even
Class
is a class, Object is a class, Module is a class and primitives likeInt32
and others are classes.Crystal object hierarchy is deeply inspired by Ruby. This peculiarity about everything being a class can be better described in this Stack Overflow response:
https://stackoverflow.com/questions/27648665/why-is-everything-an-instance-of-class-in-ruby