Live data from Hacker News

Some Smalltalk about Ruby Loops

tech.stonecharioteer.com

31–40 of 59 posts

Re: Some Smalltalk about Ruby Loops

#31
post #20

A while back I tried out SuperCollider for programmatic music generation... I distinctly remember thinking, "this language feels like some weird awkward blend of Smalltalk and Ruby". Somehow I hadn't thought of the two as similar or related to each other. Anyway, certainly you can write in this style in Python, since functions are first-class objects. It just has limits on its anonymous functions, and doesn't happen…

Implementing objects as closures interpreting messages passed as parameters is exactly how many Scheme programmers (myself included) wrote "babby's first object system" in Scheme. Such an object system is also presented in SICP.

Finally we have the following Scheme Koan:

https://people.csail.mit.edu/gregs/ll1-discuss-archive-html/...

Re: Some Smalltalk about Ruby Loops

#32
post #10

I think this misses the point. `times` is "better" than `for` because it's declarative, reads like English, etc. Which of course are opinions, but the implementation details (messaging passing or not) are irrelevant. Example: Swift and Kotlin can do `Int#times` and don't need message passing to get it done.

Dynamic types in Swift do use message passing. Int/NSInteger is a struct/value type, but NSNumber is a dynamic type that would receive a message.

Re: Some Smalltalk about Ruby Loops

#33
post #5

> But Python also looks up methods at runtime. Does that mean Python also does message passing? Not quite. I don't think Ruby's "message passing" is fundamentally different from Python's "method calls". Ultimately, both languages implementations are very similar: both look up methods by name in a hash table and then call them. IMO "message passing" is just an alternative metaphor for what Ruby does when you type `obj…

> If Ruby finds `name`, it's guaranteed to be a method whereas in Python it could be a different kind of value

This is the big difference, Ruby objects have no members other than methods, external entities cannot read data from the object only call methods; the object controls how it responds.

There's ways that seem to bypass this in Ruby, but they are cooperative, relying on calling other methods on the object, like accessing instance variables by calling object.instance_variable_get(:@foo).

Re: Some Smalltalk about Ruby Loops

#34
post #25

Leaving the comfort of lisp, I have started to wonder: why are all the looping facilities in other languages so awful? Standing on the shoulders of giants, I made this little abomination: https://rikspucko.koketteriet.se/bjoli/goof-loop It handles 98% of all loops I write, meaning I don't have to manage state (even for things like treating things like circular data). I find it removes many of the stupid errors I make…

Looping in Ruby is the opposite of awful. You only have to define an `#each` method in your class and include the `Enumerable` module, and you get a plethora of composable methods to iterate and accumulate in every which way. I find it nothing short of brilliant.

Re: Some Smalltalk about Ruby Loops

#35
post #31
post #20

A while back I tried out SuperCollider for programmatic music generation... I distinctly remember thinking, "this language feels like some weird awkward blend of Smalltalk and Ruby". Somehow I hadn't thought of the two as similar or related to each other. Anyway, certainly you can write in this style in Python, since functions are first-class objects. It just has limits on its anonymous functions, and doesn't happen…

Implementing objects as closures interpreting messages passed as parameters is exactly how many Scheme programmers (myself included) wrote "babby's first object system" in Scheme. Such an object system is also presented in SICP. Finally we have the following Scheme Koan: https://people.csail.mit.edu/gregs/ll1-discuss-archive-html/...

Amazing. I've heard both sayings before, but not the koan. Yet I somehow meditated upon it without knowing!

Re: Some Smalltalk about Ruby Loops

#36
post #34
post #25

Leaving the comfort of lisp, I have started to wonder: why are all the looping facilities in other languages so awful? Standing on the shoulders of giants, I made this little abomination: https://rikspucko.koketteriet.se/bjoli/goof-loop It handles 98% of all loops I write, meaning I don't have to manage state (even for things like treating things like circular data). I find it removes many of the stupid errors I make…

Looping in Ruby is the opposite of awful. You only have to define an `#each` method in your class and include the `Enumerable` module, and you get a plethora of composable methods to iterate and accumulate in every which way. I find it nothing short of brilliant.

Yet, iterating over several collections and accumulating values is awkward.

It is not that it is easy to implement the iteration protocol, it is that the construct for looping universally sucks. Even the awful loop macro from common lisp runs laps around most other facilities. Racket's is even less powerful, but is miles better than what python offers.

Ruby can do some destructuring, but not enough to actually be useful.

Re: Some Smalltalk about Ruby Loops

#37
post #25

Leaving the comfort of lisp, I have started to wonder: why are all the looping facilities in other languages so awful? Standing on the shoulders of giants, I made this little abomination: https://rikspucko.koketteriet.se/bjoli/goof-loop It handles 98% of all loops I write, meaning I don't have to manage state (even for things like treating things like circular data). I find it removes many of the stupid errors I make…

How is that different from select map and reduce in ruby?

Re: Some Smalltalk about Ruby Loops

#38
post #36
post #34

Earlier quoted context omitted.

Looping in Ruby is the opposite of awful. You only have to define an `#each` method in your class and include the `Enumerable` module, and you get a plethora of composable methods to iterate and accumulate in every which way. I find it nothing short of brilliant.

Yet, iterating over several collections and accumulating values is awkward. It is not that it is easy to implement the iteration protocol, it is that the construct for looping universally sucks. Even the awful loop macro from common lisp runs laps around most other facilities. Racket's is even less powerful, but is miles better than what python offers. Ruby can do some destructuring, but not enough to actually be use…

It may be somewhat awkward; zipping collections to iterate over them in unison makes the first one (the sender) seem special, while it not necessarily is. And accumulating more than one value isn't always straightforward; you usually have to reduce explicitly. But it's so much better in the general case!

Like the example you showcase your macro with. In Ruby it would be:

    lst = [[1, 2], :dud, [3, 4], [5, 6]]
    lst.grep(Array).flatten.sum
    => 21
You can see what it does at a glance, you don't have to immerse yourself inside the directives to follow the logic. And when you can't do that, declaring iterators and accumulators outside a loop and then iterating and accumulating "by hand" yields code not so different than your more complex examples.

  def partition (arr)
    yes = []
    no = []
    arr.each do |elt|
      if yield elt
        yes 

Re: Some Smalltalk about Ruby Loops

#39

Even something as basic as "if" is done with message passing and blocks in Smalltalk. There's a method named "ifTrue:ifFalse:" in Smalltalk (with each ":" expecting an argument, in this case, a block). You can also chain messages and make phrases: `anObject aMethod; anotherMethod; yourself.` The Ruby equivalent has repetition: `an_object.a_method; an_object.another_method; an_object` or requires a block: `an_object.t…

I have found that chaining things in Smalltalk get immensely painful after just a couple elements. Unlike most other languages, I find myself reaching for silly little var names for lots of different things I would normally just let flow.

Really? To each their own, but honestly, I found smalltalks way of chaining things to be one of the most elegant parts of what is admittedly a syntactically-simple language (the old "fits on a postcard" thing).

With Smalltalk, with regard to return values or chaining, you get to have your cake and eat it too.

Your methods CAN return sensible values which don't necessarily have to be the original object. BUT, if you just want to chain a bunch of sends TO A PARTICULAR OBJECT, you can use ;, and chain the sends together without requiring that each intermediate method returns the original object.

That combined with the fact that chaining sends requires no special syntax. You just write them out as a single sentence (that's what it feels like), and you can format it across multiple lines however you wish. There's no syntax requirements getting in the way.

Just finish the whole thing with a dot. Again, just like a regular sentence.

And if you find precedence or readibility becoming confusing, then just put stuff in parens to make certain portions clearer. There's absolutely no harm in doing do, even if in your particular use case the normal precedence rules would have sufficed anyway.

    Smalltalk
      complex method chaining;
      again (as mentioned previously)
      reads like English.

Re: Some Smalltalk about Ruby Loops

#40
post #4

> Leaving the handling of the loop to the method allows us to add behaviour to loops that are controlled by the object and not by the user. This is a nice way to add side-effects. No, it's an absolutely horrible way to "add side-effects" which, usually, is already a horrible idea in its own right. > Asking an object to iterate over itself allows objects to develop interfaces that dictate how to iterate. That's true i…

Strongly disagree. THE ENTIRE ETHOS of Smalltalk & Ruby is to leave things up to the object you're communicating with, rather than the call/send site.

Sure, you may not like that mindset, in which case, smalltalk/ruby are ABSOLUTELY not for you. You want something else.

Which is totally fine. Part of the reason behind the Cambrian-explosion of higher level programming paradigms since the 1960's is precisely because there are multiple ways to skin a cat, and different ways resonate with different folks.

Post reply on HN