Live data from Hacker News

"DCI" in Ruby is completely broken

tonyarcieri.com

51–60 of 67 posts

Re: "DCI" in Ruby is completely broken

#51
post #29

You know, I've been thinking about this kind of thing lately. All of this mixin, traits, monkey patching hoopla is completely nonexistent in functional programming languages. To add a new method to an object you just..write a function that takes that piece of data. Imagine a language where a call looked like this: user.doSomething(1, 2, 3) But it's just syntax sugar for this function application: doSomething(user, 1,…

In my language Magpie, function calls can have which ever appearance makes the most sense for the operation:

    prefix(arg)         // for function-like things
    arg postfix         // for "getters"
    arg infix(otherarg) // for method-like things
It's purely a syntactic distinction. Semantically, methods are always multimethods and are not tied to any receiver class. You can freely define new methods that dispatch on existing classes.

I find it works really well, though it brings in some unanticipated complexity. You'll really want multimethods or some form of argument-based polymorphism. Also, scoping get a bit more confusing if you want "overriding" to work like you expect across modules.

See: http://magpie-lang.org/multimethods.html

Re: "DCI" in Ruby is completely broken

#52
post #12

Earlier quoted context omitted.

Completely agreed, the title is a red herring and serves to dissuade people from giving DCI a try. "It's too slow" is not an argument against DCI, it's an argument for fixing a slow implementation of #extend or using a different method.

Why not do DCI with delegation instead of mixins?

Because in general, delegation tends to lead to object schizophrenia. Specifically, SimpleDelegator will leak the original delegatee object when a delegated method returns `self`.

     s = "foo"
     
     d = SimpleDelegator.new s

     s2 = d 
I think SimpleDelegator is really neat but totally dangerous. Doesn't this ring alarm bells with you?

  # delegate.rb L117
  #
  # Returns true if two objects are considered of equal value.
  #
  def ==(obj)
    return true if obj.equal?(self)
    self.__getobj__ == obj
  end

Re: "DCI" in Ruby is completely broken

#53
post #36

Earlier quoted context omitted.

But you cannot do it the other way, eg: def foo(bar, baz): print bar.baz + baz f = Foo() f.foo(3) # error

Claiming "f.foo" should work when "foo" is a freestanding function strikes me as nonsensical, as the "." operator is a namespace operator, suggesting names that are within the namespace of "Foo". Though Postgresql supports this pattern ( http://www.postgresql.org/docs/9.2/static/xfunc-sql.html#XFU... ). I think it's awkward there too, and has the caveat "it's unwise to give a function that takes a single composite-ty…

In static languages this really isn't a big deal, since you can dispatch based on type. Things definitely get more awkward if you can do things like define new types at runtime, though.

Re: "DCI" in Ruby is completely broken

#54
post #48
post #25

Earlier quoted context omitted.

It depends. Is your app CPU-bound? If so, then DCI probably isn't a great idea for you. In fact, building it in Ruby may not be the best idea. But if your app is IO-bound (like most Rails apps), huge and it takes new developers weeks to get up to speed, then the gains from having a simple, modular code-base should save you developer-time (and hence salaries), which are much more expensive than CPUs. Having said that,…

This DCI stuff sounds like a quick way to make an app CPU-bound, if it wasn't already.

Ruby may be slow but my apps still spend more time waiting on complex database queries than anything else (unless I'm using the Jbuilder gem to build JSON outputs, in which case I might as well make a cup of tea waiting for a call to return)

Re: "DCI" in Ruby is completely broken

#55
post #29

You know, I've been thinking about this kind of thing lately. All of this mixin, traits, monkey patching hoopla is completely nonexistent in functional programming languages. To add a new method to an object you just..write a function that takes that piece of data. Imagine a language where a call looked like this: user.doSomething(1, 2, 3) But it's just syntax sugar for this function application: doSomething(user, 1,…

In my language Magpie, function calls can have which ever appearance makes the most sense for the operation: prefix(arg) // for function-like things arg postfix // for "getters" arg infix(otherarg) // for method-like things It's purely a syntactic distinction. Semantically, methods are always multimethods and are not tied to any receiver class. You can freely define new methods that dispatch on existing classes. I fi…

Magpie is so lovely, i want to give it flowers. Do you think it'll ever reach something near production equality, or will it "always" be a "toy"?

Re: "DCI" in Ruby is completely broken

#57
post #34
post #21

Earlier quoted context omitted.

It isn't so odd in Ruby. Ruby has always been a duck typing land. If it quacks, it is a duck. There's even a method missing handler so you can respond to any method call whatsoever. People can and do add methods directly to even built-in classes as well, the equivalent of modifying the class prototype in Javascript. So method calls are considered more messages in Ruby and saying a class will respond differently to a…

>It isn't so odd in Ruby. Ruby has always been a duck typing land. If it quacks, it is a duck. There's even a method missing handler so you can respond to any method call whatsoever. What's the benefit of this kind of typing, though? I'm pretty much just a C hacker these days, so I'm pretty ignorant about Ruby, but does this apply to the object or to the class? It seems simpler, especially on a conceptual level, to j…

Side note, duck typing is not inherently slow. Some people assume since many duck-typed languages are slow that there is some causation going on.

Go is way faster than Ruby and extensively uses duck typing everywhere (but is also statically typed and not interpreted-). My point is duck typing is not the reason Ruby is so slow.

Re: "DCI" in Ruby is completely broken

#58
post #44

Earlier quoted context omitted.

At a code level - no need to write the delegation methods/macros. At the design level - flat hierarchy At an abstract level - thinking in terms of objects, not classes.

> At a code level - no need to write the delegation methods/macros. You don't have to. They're built into SimpleDelegator. Syntactically the difference is you'd write: class MyThing instead of: module MyThing And do: MyThing.new(obj) instead of: obj.extend(myThing) > At an abstract level - thinking in terms of objects, not classes. It seems to me like you're trying to use a module to solve a problem which can be solv…

With DCI do you ever need to extend/include multiple modules? Would this single-inheritance approach work?

Re: "DCI" in Ruby is completely broken

#59
post #29

You know, I've been thinking about this kind of thing lately. All of this mixin, traits, monkey patching hoopla is completely nonexistent in functional programming languages. To add a new method to an object you just..write a function that takes that piece of data. Imagine a language where a call looked like this: user.doSomething(1, 2, 3) But it's just syntax sugar for this function application: doSomething(user, 1,…

That's exactly how these OOP languages get translated into C, so the difference would be having a method dispatch table per class or having a global system for multiple dispatch.

Re: "DCI" in Ruby is completely broken

#60
post #58
post #44

Earlier quoted context omitted.

> At a code level - no need to write the delegation methods/macros. You don't have to. They're built into SimpleDelegator. Syntactically the difference is you'd write: class MyThing instead of: module MyThing And do: MyThing.new(obj) instead of: obj.extend(myThing) > At an abstract level - thinking in terms of objects, not classes. It seems to me like you're trying to use a module to solve a problem which can be solv…

With DCI do you ever need to extend/include multiple modules? Would this single-inheritance approach work?

As long as the interactions you're working with don't implement the same methods, it would be trivially easy:

  class Account; …; end
  class Withdrawer 
At least that's how I understand it. I'm not convinced that DCI is worth it, but…I don't yet have a need for it in the application that I'm working with.
Post reply on HN