DEV Community

Discussion on: Causes - a programming language feature concept

Collapse
 
baweaver profile image
Brandon Weaver

It's possible to write the first part, haven't taken a shot at satisfying yet:

module Causation
  def self.included(klass)
    klass.extend(ClassMethods)
  end

  module ClassMethods
    def causes(&effect)
      @causation     = true
      @caused_effect = effect
    end

    def method_added(method_name)
      return unless @causation

      @causation = false

      effect = @caused_effect
      original_method_name = "#{method_name}_without_effect".to_sym

      alias_method original_method_name, method_name

      define_method(method_name) do |*args, &fn|
        original_result = send(original_method_name, *args, &fn)
        validation      = instance_exec(original_result, &effect)

        raise 'unintended!' unless validation
      end
    end
  end
end

class Something
  include Causation

  attr_reader :v

  def initialize(v) @v = v end

  causes { v.nil? }
  def boom(v = nil); @v = v end
end

If you'd like I can write a bit more on how exactly this works, but the short of it is that Causation intercepts all added methods in a class. It'll ignore anything without a causes call above it.

The fun part was trying to get the block to evaluate in the context of the instance, and instance_exec ended up working for that one. Admittedly didn't know about that one before, so I'd have to read more into it to explain beyond that it allows injection of variables or state into the evaluation and still lets you rebind the block to execute in the instance.

Now as far as the actual content of the article itself, you may enjoy ideas like Sorbet and other static typing implementations. They don't quite give the flexibility that this does as far as guarantees of output via arbitrary functions, but could inspire some other interesting ideas.

Collapse
 
aaronc81 profile image
Aaron Christiansen

Awesome start at implementation!

I'm actually really enjoying Sorbet - I've already developed two tools for it (Sord, to generate signatures from YARD docs, and Parlour, a plugin framework). The causes syntax in this article was inspired by Sorbet's sig. I thought of this idea when thinking about how Sorbet could be taken further.