Project

General

Profile

Actions

Feature #6806

closed

Support functional programming: forbid instance/class variables for ModuleName::method_name, allow for ModuleName.method_name

Added by alexeymuranov (Alexey Muranov) over 12 years ago. Updated about 4 years ago.

Status:
Feedback
Target version:
-
[ruby-core:46829]

Description

What would you say about this proposal? Is there a better alternative?

I suggest to support functional programming in Ruby by making module methods called with ModuleName::method_name syntax raise an exception if the method uses instance or class variables (instance variables of the singleton class, of course).
If i understand correctly, currently ModuleName::method_name and ModuleName.method_name behave identically, so i propose that they be different:

module M
  module_function
    def f(x)
      x*x
    end
    def g(x)
      @x ||= x
      @x*@x
    end
end

M.f(2) # => 4
M.g(2) # => 4
M::f(3) # => 9
M::g(3) # => Error: instance variable `@x` used in a functional call `M::g`

Current behavior:

M.f(2) # => 4
M.g(2) # => 4
M::f(3) # => 9
M::g(3) # => 4

Updated by alexeymuranov (Alexey Muranov) over 12 years ago

I think that if you tell a new person that M::f and M.f are the same in Ruby, they won't believe at first. So why keeping them the same?

I do not know how to be with the use of global variables in M::f. I imagine there are other details to discuss.

This feature wouldn't ensure truly functional programming, but i hope it can introduce a "good practice" of making it clear from the call syntax if a method can change the state of the object. In other words, i propose that when x::f(y) is called, the state of the object x be frozen, and unfrozen after the return from f, so x act simply as a namespace.

I do not know whether it would be better for x::f to allow read-only access to the state of x, or no access at all. Probably read-only access makes better sense, given impossibility to exclude interaction with other data anyway.

Another approach could be to forbid a function called with :: prefix to change the state of any object that is not created by it, and to forbid to read the state of any object that is not accessible through the state of self or the state of one of the arguments.

If the feature is implemented with read-only access to any existing data, this syntax can be used to give a precise meaning to non-exclaiming methods: a::map instead of a.map, and a.map! stays as is.

To determine what objects are "accessible" through the state of a given object, i think it should be forbidden to go "up" with methods like "#class" or "#superclass" and then go "down". In the direction "up", only the object's class and its ancestors should be accessible, i think.

Updated by drbrain (Eric Hodel) over 12 years ago

  • Assignee set to matz (Yukihiro Matsumoto)
  • Target version set to 3.0

This would break compatibility with much ruby code.

Updated by alexeymuranov (Alexey Muranov) over 10 years ago

Besides functional programming, IMO this would support command–query separation.

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

  • Description updated (diff)
  • Status changed from Open to Feedback

It seems unrelated to "functional programming" at all.

Updated by alexeymuranov (Alexey Muranov) over 10 years ago

I meant that a function called like Math::sin would be required to return same values (for same arguments) every time. Maybe i did not explain this well. Foo.bar, on the other hand, would not have this restriction.

Same could be generalized to mutable (non-constant) objects, but there the distinction could be harder to make. Maybe x::to_s but x.update!?

P.S. Thanks for reformatting the proposal.

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

It's just your style.
I use Math.sin and so on.

Actions #7

Updated by naruse (Yui NARUSE) about 4 years ago

  • Target version deleted (3.0)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0