Crystal: Add static keyword as alias for class_*

Created on 9 Jul 2017  路  14Comments  路  Source: crystal-lang/crystal

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

https://carc.in/#/r/2bps

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

https://carc.in/#/r/2bpv

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

discussion compiler

Most helpful comment

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

All 14 comments

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

https://carc.in/#/r/2bq4

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Papierkorb picture Papierkorb  路  3Comments

lgphp picture lgphp  路  3Comments

will picture will  路  3Comments

lbguilherme picture lbguilherme  路  3Comments

asterite picture asterite  路  3Comments