Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an analog in Scala for the Rails "returning" method?

In Rails, one could use:

returning Person.create do |p|
  p.first_name = "Collin"
  p.last_name = "VanDyck"
end

Avoiding having to do this:

person = Person.create
person.first_name = "Collin"
person.last_name = "VanDyck"
person

I think the former way is cleaner and less repetitive. I find myself creating this method in my Scala projects:

def returning[T](value: T)(fn: (T) => Unit) : T = {
  fn(value)
  value
}

I know that it is of somewhat limited utility due to the tendency of objects to be immutable, but for example working with Lift, using this method on Mapper classes works quite well.

Is there a Scala analog for "returning" that I'm not aware of? Or, is there a similar way to do this in Scala that's more idiomatic?

like image 623
Collin Avatar asked Oct 22 '10 12:10

Collin


3 Answers

Your method looks fine, though I normally do this by adding a method for side-effects, which can include changing internal state (or also stuff like println):

class SideEffector[A](a: A) {
  def effect(f: (A => Any)*) = { f.foreach(_(a)); a }
}
implicit def can_have_side_effects[A](a: A) = new SideEffector(a)

scala> Array(1,2,3).effect(_(2) = 5 , _(0) = -1)
res0: Array[Int] = Array(-1, 2, 5)

Edit: just in case it's not clear how this would be useful in the original example:

Person.create.effect(
  _.first_name = "Collin",
  _.last_name = "VanDyck"
)

Edit: changed the name of the method to "effect". I don't know why I didn't go that way before--side effect, not side effect for the naming.

like image 158
Rex Kerr Avatar answered Nov 04 '22 04:11

Rex Kerr


Can't really improve much on what you've already written. As you quite correctly pointed out, idiomatic Scala tends to favour immutable objects, so this kind of thing is of limited use.

Plus, as a one-liner it's really not that painful to implement yourself if you need it!

def returning[T](value: T)(fn: T => Unit) : T = { fn(value); value }
like image 38
Kevin Wright Avatar answered Nov 04 '22 03:11

Kevin Wright


I would do:

scala> case class Person(var first_name: String = "", var last_name: String = "")
defined class Person

scala> Person(first_name="Collin", last_name="VanDyck")
res1: Person = Person(Collin,VanDyck)
like image 3
pedrofurla Avatar answered Nov 04 '22 04:11

pedrofurla