From: raja@... (Raja S.) Date: 2000-12-09T18:10:04+09:00 Subject: [ruby-talk:6957] return value of mutating methods I recently came across this issue in some code I was developing. Going thru the archives I saw that there was a discussion of this sometime ago but I wasn't sure if a consensus had been reached. Should the return value of mutating methods (syntactically indicated with a suffix 'bang') be specified? Should they return value be nil or the object being modified? For example, suppose you want to read in a line, remove a terminating newline and downcase it. Couple of choices are: line = line.chomp.downcase # creates unnecessary garbage vs line.chomp! ; line.downcase! # verbose, seems in-elegant There is an expression elegance if we were able to say: line.chomp!.downcase! In order to be able to chain mutating method calls (and the resulting conciseness of expression) I would vote for all builtin mutating methods to return the object so changed. A similar convention being used for all user written mutating methods. * I'm not sure if there is a "right" or "wrong" answer to this question of (nil vs modified object return value). Some other language communities have dicussed long and hard on this issue ... The Scheme community have -long- discussed this and have moved in favor of leaving the return value of side-effecting routines to be "undefined". Different implementations, depending on the context return different values, e.g., (define a 3) ;-> 'a' (set! a 3) ;-> 3 etc while others (Chez Scheme) have explicitly created an "undefined" object (#). In OOSC Meyer points out the benefits of conceptually separating two types of methods "queries" (no side-effect) from "commands (side-effects). But his argument is more in the context of testing for pre/post conditions and invariants --- one can't test using a query that also changes its argument. A sort of CS equivalent of "Heisenberg uncertainty" :-). The prototypical example being the problem of testing a stack with an implementation of #pop which returns the top value -and- removes it. He prefers #top (query) and #pop (command which just removes the top element without returning a value). Ruby (like Scheme) has the very nice ability to -syntactically- differentiate between queries and commands. So it seems that for the Stack#pop objection, if one provides #top and #pop! (return + mutate) and uses the convention that no "bang" methods should be used in pre/post/invariant testing things should be OK. Raja