This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Style question: declarative vs procedural

11 replies
Marcus Downing
Joined: 2011-02-08,
User offline. Last seen 42 years 45 weeks ago.
I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
class Foo extends Feature {  val name = "Foo"  def require = List(Bar, Qux)  override def before = List(Qux)  override def after = List(Bar)}

An alternative is to declare these things using methods:
class Foo extends Feature {  val name = "Foo"  require(Bar, Qux)  before Qux  after Bar}

The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?
Aydjen
Joined: 2009-08-21,
User offline. Last seen 1 year 28 weeks ago.
Re: Style question: declarative vs procedural

Hi,

Marcus Downing asked:
> The second certainly reads more easily, but it has a downside: the class has
> now become mutable, something I'm doing my best to avoid. So is the syntactic
> niceness of the second worth the tradeoff of making the code procedural rather
> than declarative?
>

 
I'd say: no.
 
Is Feature a trait or a class? If it's a class, why not ask for name, required,
before and after as constructor parameters?
 
class Feature(val name: String, val required: Seq[Any])(val before: Seq[Any] =
required, val after: Seq[Any] = required)
 
(I took Any (and some other assumptions) here because I have no idea about the
type constraints of your methods.) 
 
Then you could say:
 
class Foo extends Feature("Foo", Seq(...))(Seq(...), Seq(...))
 
or
 
class Foo extends Feature(
  name = "Foo",
  required = Seq(...)
)(
  before = Seq(...),
  after = Seq(...)
)
 
or leave after as default
 
class Foo extends Feature(
  name = "Foo",
  required = Seq(...)
)(
  before = Seq(...) 
)
 
I hope that helped a bit.
 
Kind regards
Andreas 

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Style question: declarative vs procedural

if you want to keep the syntax and the immutability:

class Foo extends Feature {//feature has an abstract val called meta
val meta = Meta(
name = "i am sonic",
requires = List(a,b),
before = a,
after = b)
}

class Meta(name, require, before, after) {
}

-------- Original-Nachricht --------
> Datum: Tue, 13 Dec 2011 01:54:32 -0800 (PST)
> Von: Marcus Downing
> An: scala-user@googlegroups.com
> Betreff: [scala-user] Style question: declarative vs procedural

> I'm designing a library and need
> to
> provide a way for implementing classes to state certain facts about
> themselves. At the moment this looks like:
>
> class Foo extends Feature {
> val name = "Foo"
> def require = List(Bar, Qux)
> override def before = List(Qux)
> override def after = List(Bar)
> }
>
>
> An alternative is to declare these things using methods:
>
> class Foo extends Feature {
> val name = "Foo"
> require(Bar, Qux)
> before Qux
> after Bar
> }
>
>
> The second certainly reads more easily, but it has a downside: the class
> has now become mutable, something I'm doing my best to avoid. So is the
> syntactic niceness of the second worth the tradeoff of making the code
> procedural rather than declarative?

nilskp
Joined: 2009-01-30,
User offline. Last seen 1 year 27 weeks ago.
Re: Style question: declarative vs procedural
On Tue, Dec 13, 2011 at 3:54 AM, Marcus Downing <marcus.downing@gmail.com> wrote:
I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
class Foo extends Feature {  val name = "Foo"   def require = List(Bar, Qux)  override def before = List(Qux)  override def after = List(Bar) }

An alternative is to declare these things using methods:
class Foo extends Feature {  val name = "Foo"  require(Bar, Qux)   before Qux  after Bar}

The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?

It may appear to be syntactic niceness, but is it really? The former is immutable and will provide you with nice compiler errors if you forget them. The latter not so much. You could also pass them in the constructor, but that's even uglier syntactically, and unnecessary because the values are not needed for construction of Feature, only usage.
Tony Morris
Joined: 2008-12-19,
User offline. Last seen 30 weeks 4 days ago.
Re: Style question: declarative vs procedural

No.

On Dec 13, 2011 7:54 PM, "Marcus Downing" <marcus.downing@gmail.com> wrote:
I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
class Foo extends Feature {  val name = "Foo"   def require = List(Bar, Qux)  override def before = List(Qux)  override def after = List(Bar) }

An alternative is to declare these things using methods:
class Foo extends Feature {  val name = "Foo"  require(Bar, Qux)   before Qux  after Bar}

The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Style question: declarative vs procedural
What about:
abstract class Feature(val name: String, val require: Seq[Feature] = Seq.empty, val before: Seq[Feature] = Seq.empty, val after: Seq[Feature] = Seq.empty) {}
class Foo extends Feature(   name = "Foo",  require = Seq(Bar, Quz)  // No more needed if I don't need different values.) {
  // Normal overrides here....}
On Tue, Dec 13, 2011 at 4:54 AM, Marcus Downing <marcus.downing@gmail.com> wrote:
I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
class Foo extends Feature {  val name = "Foo"   def require = List(Bar, Qux)  override def before = List(Qux)  override def after = List(Bar) }

An alternative is to declare these things using methods:
class Foo extends Feature {  val name = "Foo"  require(Bar, Qux)   before Qux  after Bar}

The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?

Aydjen
Joined: 2009-08-21,
User offline. Last seen 1 year 28 weeks ago.
Re: Style question: declarative vs procedural

Hi,

isn't that pretty much exactly like my first answer in this thread? :)

Kind regards
Andreas

Josh Suereth wrote:

> What about:
>
> abstract class Feature(val name: String, val require: Seq[Feature] = Seq.empty, val before: Seq[Feature] = Seq.empty, val after: Seq[Feature] = Seq.empty) {}
>
> class Foo extends Feature(
> name = "Foo",
> require = Seq(Bar, Quz)
> // No more needed if I don't need different values.
> ) {
>
> // Normal overrides here....
> }
>
> On Tue, Dec 13, 2011 at 4:54 AM, Marcus Downing wrote:
> I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
>
> class Foo extends Feature {
> val name = "Foo"
> def require = List(Bar, Qux)
> override def before = List(Qux)
> override def after = List(Bar)
> }
>
> An alternative is to declare these things using methods:
>
> class Foo extends Feature {
> val name = "Foo"
> require(Bar, Qux)
> before Qux
> after Bar
> }
>
> The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?
>

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Style question: declarative vs procedural
Opps, that's correct.  Sorry, I got to this one pretty late :)
Note: <collection>.empty rather than Seq() is a meme I'm trying to push though!
- Josh

On Wed, Dec 14, 2011 at 9:39 AM, Andreas Flierl <andreas@flierl.eu> wrote:
Hi,

isn't that pretty much exactly like my first answer in this thread? :)

Kind regards
Andreas

Josh Suereth wrote:

> What about:
>
> abstract class Feature(val name: String, val require: Seq[Feature] = Seq.empty, val before: Seq[Feature] = Seq.empty, val after: Seq[Feature] = Seq.empty) {}
>
> class Foo extends Feature(
>   name = "Foo",
>   require = Seq(Bar, Quz)
>   // No more needed if I don't need different values.
> ) {
>
>   // Normal overrides here....
> }
>
> On Tue, Dec 13, 2011 at 4:54 AM, Marcus Downing <marcus.downing@gmail.com> wrote:
> I'm designing a library and need to provide a way for implementing classes to state certain facts about themselves. At the moment this looks like:
>
> class Foo extends Feature {
>   val name = "Foo"
>   def require = List(Bar, Qux)
>   override def before = List(Qux)
>   override def after = List(Bar)
> }
>
> An alternative is to declare these things using methods:
>
> class Foo extends Feature {
>   val name = "Foo"
>   require(Bar, Qux)
>   before Qux
>   after Bar
> }
>
> The second certainly reads more easily, but it has a downside: the class has now become mutable, something I'm doing my best to avoid. So is the syntactic niceness of the second worth the tradeoff of making the code procedural rather than declarative?
>


Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Style question: declarative vs procedural


On Tuesday, December 13, 2011, Marcus Downing <marcus.downing@gmail.com> wrote:
>   before Qux
>   after Bar

You can't really do that. scalac sees that as "call method Qux of value before." You need parenthesis.
Marcus Downing
Joined: 2011-02-08,
User offline. Last seen 42 years 45 weeks ago.
Re: Style question: declarative vs procedural
Named, default arguments does look like a nice way of doing it, that has reasonable syntax as well as immutability. Feature is currently a trait, but can be a class for the sake of getting this configuration right.
Why the split parameter list though?
class Foo extends Feature(  name = "Foo",  required = List(...))(  before = List(...) )

vs
class Foo extends Feature(  name = "Foo",  required = List(...),  before = List(...) )

Thanks to Andreas - and Josh - for the answer. 
Aydjen
Joined: 2009-08-21,
User offline. Last seen 1 year 28 weeks ago.
Re: Style question: declarative vs procedural

Hi,

the default arguments of the second parameter list can use the ones from the
first, e.g. the default value for "before" is whatever was given to "required"
in my example. I just wanted to show you that this is possible, in case you'd
need it.
 
Kind regards
Andreas 
 

Marcus Downing wrote:

> Named, default arguments does look like a nice way of doing it, that has
> reasonable syntax as well as immutability. Feature is currently a trait, but
> can be a class for the sake of getting this configuration right. 
> Why the split parameter list though?
>  
>
> > class Foo extends Feature(
> >   name = "Foo",
> >   required = List(...)
> > )(
> >   before = List(...) 
> > )
> >
 
> vs
>  
>
> > class Foo extends Feature(
> >
> >   name = "Foo",
> >
> >   required = List(...),
> >
> >   before = List(...) 
> >
> > )
> >
> >

 
 

Marcus Downing
Joined: 2011-02-08,
User offline. Last seen 42 years 45 weeks ago.
Re: Style question: declarative vs procedural
Ah, I see - DRY. The trade-off is that it requires the second brackets to be present all the time.
Having implemented this, I can tell just from the change to all my test cases that it's an improvement in readability. Not only is is shorter, more importantly the cases with and without each of the optional arguments look less similar, so it's easier to tell the intent of code with a glance.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland