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

A scala anti pattern -- looking for a name

33 replies
Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.

Hi,

A committer on the Apache Clerezza incubator project has discovered a new anti-pattern.

He has written some code that requires one to weave import statements into one's code if it is going
to give the right results. Here is an example:

val ez1: EZMGraph...
val ez2: EZMGraph...

import ez1._
ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri

import ez2._
ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri

import ez1._
ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri

If the second or third imports are not added, the wrong graph container will be
filled with the relation.

I believe that any code that requires one to do that is evidently an anti-pattern.

But you may be intrigued to find out how one can generate such an anti-pattern in Scala?
The answer in short is by writing an implicit with an hidden variable

protected trait TcDependentConversions extends TcIndependentConversions {

def baseTc: TripleCollection

implicit def toRichGraphNode(resource: Resource) = {
new RichGraphNode(new GraphNode(resource, baseTc))
}
}

and then writing a class that extends that trait

class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions

In fact the classes are all here:

http://svn.apache.org/viewvc/incubator/clerezza/tags/clerezza-201107/rdf...

I wrote a patch for this code https://issues.apache.org/jira/browse/CLEREZZA-603
but I am told that this cannot be accepted until a name for this anti-pattern has
been found. I therefore suggest that we call it the Reto anti-pattern after the name
of its author and in honor of him. But perhaps he was not the first to discover it,
and we should not be assigning an original claim where it is not warranted.

Henry

Social Web Architect
http://bblfish.net/

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: A scala anti pattern -- looking for a name
 I'd call this 'too much pimpin'.  THere's probably a simpler no-implicit DSL that you could provide that looks and feels the same, but without the pitfalls.
On Tue, Jul 19, 2011 at 10:26 AM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Hi,

 A committer on the Apache Clerezza incubator project has discovered a new anti-pattern.

He has written some code that requires one to weave import statements into one's code if it is going
to give the right results. Here is an example:

 val ez1: EZMGraph...
 val ez2: EZMGraph...

 import ez1._
 ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri

 import ez2._
 ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri

 import ez1._
 ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri

If the second or third imports are not added, the wrong graph container will be
filled with the relation.

I believe that any code that requires one to do that is evidently an anti-pattern.

But you may be intrigued to find out how one can generate such an anti-pattern in Scala?
The answer in short is by writing an implicit with an hidden variable

protected trait TcDependentConversions extends TcIndependentConversions {

 def baseTc: TripleCollection

 implicit def toRichGraphNode(resource: Resource) = {
       new RichGraphNode(new GraphNode(resource, baseTc))
 }
}

and then writing a class that extends that trait

class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions

In fact the classes are all here:

http://svn.apache.org/viewvc/incubator/clerezza/tags/clerezza-201107/rdf.scala.utils//src/main/scala/org/apache/clerezza/rdf/scala/utils/

I wrote a patch for this code https://issues.apache.org/jira/browse/CLEREZZA-603
but I am told that this cannot be accepted until a name for this anti-pattern has
been found. I therefore suggest that we call it the Reto anti-pattern after the name
of its author and in honor of him. But perhaps he was not the first to discover it,
and we should not be assigning an original claim where it is not warranted.

 Henry


Social Web Architect
http://bblfish.net/


Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 19 Jul 2011, at 16:31, Josh Suereth wrote:
 I'd call this 'too much pimpin'.

Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?
 THere's probably a simpler no-implicit DSL that you could provide that looks and feels the same, but without the pitfalls.

Yes, that is what the patch 
  https://github.com/bblfish/clerezza/commit/85628443598eaf817f0b20809cc7c5f6916a7f82
does. It removes the inheritance from the trait containing the implicit, and creates a few explicit methods that have the same effect. In my view the code is a lot more readable too as a result.
  Henry

On Tue, Jul 19, 2011 at 10:26 AM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Hi,

 A committer on the Apache Clerezza incubator project has discovered a new anti-pattern.

He has written some code that requires one to weave import statements into one's code if it is going
to give the right results. Here is an example:

 val ez1: EZMGraph...
 val ez2: EZMGraph...

 import ez1._
 ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri

 import ez2._
 ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri

 import ez1._
 ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri

If the second or third imports are not added, the wrong graph container will be
filled with the relation.

I believe that any code that requires one to do that is evidently an anti-pattern.

But you may be intrigued to find out how one can generate such an anti-pattern in Scala?
The answer in short is by writing an implicit with an hidden variable

protected trait TcDependentConversions extends TcIndependentConversions {

 def baseTc: TripleCollection

 implicit def toRichGraphNode(resource: Resource) = {
       new RichGraphNode(new GraphNode(resource, baseTc))
 }
}

and then writing a class that extends that trait

class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions

In fact the classes are all here:

http://svn.apache.org/viewvc/incubator/clerezza/tags/clerezza-201107/rdf.scala.utils//src/main/scala/org/apache/clerezza/rdf/scala/utils/

I wrote a patch for this code https://issues.apache.org/jira/browse/CLEREZZA-603
but I am told that this cannot be accepted until a name for this anti-pattern has
been found. I therefore suggest that we call it the Reto anti-pattern after the name
of its author and in honor of him. But perhaps he was not the first to discover it,
and we should not be assigning an original claim where it is not warranted.

 Henry


Social Web Architect
http://bblfish.net/



Social Web Architect
http://bblfish.net/
Chris Lewis
Joined: 2009-04-08,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

"Implicitly Aroused."

It seems one of the most overused and abused features to scala
new-comers is implicit conversions. They're useful sometimes, but a real
pain lots of times. I'll defer to Josh Suereth's talks on why, but that
code snippet is a shining example.

-chris

On 7/19/11 10:26 AM, Henry Story wrote:
> Hi,
>
> A committer on the Apache Clerezza incubator project has discovered a new anti-pattern.
>
> He has written some code that requires one to weave import statements into one's code if it is going
> to give the right results. Here is an example:
>
> val ez1: EZMGraph...
> val ez2: EZMGraph...
>
> import ez1._
> ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri
>
> import ez2._
> ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>
> import ez1._
> ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri
>
> If the second or third imports are not added, the wrong graph container will be
> filled with the relation.
>
> I believe that any code that requires one to do that is evidently an anti-pattern.
>
> But you may be intrigued to find out how one can generate such an anti-pattern in Scala?
> The answer in short is by writing an implicit with an hidden variable
>
> protected trait TcDependentConversions extends TcIndependentConversions {
>
> def baseTc: TripleCollection
>
> implicit def toRichGraphNode(resource: Resource) = {
> new RichGraphNode(new GraphNode(resource, baseTc))
> }
> }
>
> and then writing a class that extends that trait
>
> class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions
>
> In fact the classes are all here:
>
> http://svn.apache.org/viewvc/incubator/clerezza/tags/clerezza-201107/rdf...
>
> I wrote a patch for this code https://issues.apache.org/jira/browse/CLEREZZA-603
> but I am told that this cannot be accepted until a name for this anti-pattern has
> been found. I therefore suggest that we call it the Reto anti-pattern after the name
> of its author and in honor of him. But perhaps he was not the first to discover it,
> and we should not be assigning an original claim where it is not warranted.
>
> Henry
>
>
> Social Web Architect
> http://bblfish.net/
>

Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 19 Jul 2011, at 16:40, Chris Lewis wrote:

> "Implicitly Aroused."
>
> It seems one of the most overused and abused features to scala new-comers is implicit conversions. They're useful sometimes, but a real pain lots of times. I'll defer to Josh Suereth's talks on why, but that code snippet is a shining example.

Yes, I completely agree. In fact that is what another of my patches was out to solve, the one I
posted in order to solve "EzMGraph imports too many implicits"

https://issues.apache.org/jira/browse/CLEREZZA-599

There the author imported a dozen or more implicits into a class. As a result when one uses an IDE one gets a bunch of methods that appear that have nothing to do with the class. I posted some pictures that show this anti-pattern in action on the CLEREZZA-599 issue.

Chris Lewis may want to use this as an example in his future rants.

My patch was not accepted, probably again because the author of the code wishes his name to be
associated with this anti-pattern first.

Henry

>
> -chris
>
> On 7/19/11 10:26 AM, Henry Story wrote:
>> Hi,
>>
>> A committer on the Apache Clerezza incubator project has discovered a new anti-pattern.
>>
>> He has written some code that requires one to weave import statements into one's code if it is going
>> to give the right results. Here is an example:
>>
>> val ez1: EZMGraph...
>> val ez2: EZMGraph...
>>
>> import ez1._
>> ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri
>>
>> import ez2._
>> ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>>
>> import ez1._
>> ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri
>>
>> If the second or third imports are not added, the wrong graph container will be
>> filled with the relation.
>>
>> I believe that any code that requires one to do that is evidently an anti-pattern.
>>
>> But you may be intrigued to find out how one can generate such an anti-pattern in Scala?
>> The answer in short is by writing an implicit with an hidden variable
>>
>> protected trait TcDependentConversions extends TcIndependentConversions {
>>
>> def baseTc: TripleCollection
>>
>> implicit def toRichGraphNode(resource: Resource) = {
>> new RichGraphNode(new GraphNode(resource, baseTc))
>> }
>> }
>>
>> and then writing a class that extends that trait
>>
>> class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions
>>
>> In fact the classes are all here:
>>
>> http://svn.apache.org/viewvc/incubator/clerezza/tags/clerezza-201107/rdf...
>>
>> I wrote a patch for this code https://issues.apache.org/jira/browse/CLEREZZA-603
>> but I am told that this cannot be accepted until a name for this anti-pattern has
>> been found. I therefore suggest that we call it the Reto anti-pattern after the name
>> of its author and in honor of him. But perhaps he was not the first to discover it,
>> and we should not be assigning an original claim where it is not warranted.
>>
>> Henry
>>
>>
>> Social Web Architect
>> http://bblfish.net/
>>
>

Social Web Architect
http://bblfish.net/

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: A scala anti pattern -- looking for a name


On Tue, Jul 19, 2011 at 10:43 AM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:

On 19 Jul 2011, at 16:31, Josh Suereth wrote:
 I'd call this 'too much pimpin'.

Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?
 THere's probably a simpler no-implicit DSL that you could provide that looks and feels the same, but without the pitfalls.

Yes, that is what the patch 
  https://github.com/bblfish/clerezza/commit/85628443598eaf817f0b20809cc7c5f6916a7f82
does. It removes the inheritance from the trait containing the implicit, and creates a few explicit methods that have the same effect. In my view the code is a lot more readable too as a result.
  Henry


Definitely.   I can't stress enough to people that implicits should be reserved for situations where they are *required* as opposed to just fun to use.
- Josh 
nilskp
Joined: 2009-01-30,
User offline. Last seen 1 year 27 weeks ago.
Re: A scala anti pattern -- looking for a name
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?
Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 19 Jul 2011, at 16:53, Nils Kilden-Pedersen wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?

Well that this code is an anti-pattern is obvious to anyone who looks at it, it seems to me.But after a week of careful explanations of what is happening the author of the original codetoday requested: 
"I think it's important to identify anti-pattern. Post a link here if you document the anti-pattern you think you've discovered on the scala mailing list"
http://mail-archives.apache.org/mod_mbox/incubator-clerezza-dev/201107.mbox/browser
This suggests to me that he wishes to be associated with it, and remembered for it.
Henry
Social Web Architect
http://bblfish.net/
Carl-Eric Menzel
Joined: 2009-04-25,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On Tue, 19 Jul 2011 10:40:57 -0400
Chris Lewis wrote:

> "Implicitly Aroused."
>
> It seems one of the most overused and abused features to scala
> new-comers is implicit conversions. They're useful sometimes, but a
> real pain lots of times. I'll defer to Josh Suereth's talks on why,
> but that code snippet is a shining example.

I get the impression that implicits are suffering from @Syndrome.
Remember when annotations were all new and shiny with Java 1.5 and
people sprinkled them everywhere like magic pixie dust? Looks like
implicits are just as shiny and fun right now as annotations used to be.

Carl-Eric

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: A scala anti pattern -- looking for a name
Better to make a viral meme.   "Oh, don't do that, or implicit-cat will get you"


On Tue, Jul 19, 2011 at 10:53 AM, Nils Kilden-Pedersen <nilskp [at] gmail [dot] com> wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A scala anti pattern -- looking for a name
"Gimp my Library"

On Tue, Jul 19, 2011 at 5:24 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:
Better to make a viral meme.   "Oh, don't do that, or implicit-cat will get you"


On Tue, Jul 19, 2011 at 10:53 AM, Nils Kilden-Pedersen <nilskp [at] gmail [dot] com> wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
marc
Joined: 2011-06-02,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name
Winner.
On Tuesday, July 19, 2011 8:46:24 AM UTC-7, √iktor Klang wrote:
"Gimp my Library"

On Tue, Jul 19, 2011 at 5:24 PM, Josh Suereth <joshua [dot] [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Better to make a viral meme.   "Oh, don't do that, or implicit-cat will get you"


On Tue, Jul 19, 2011 at 10:53 AM, Nils Kilden-Pedersen <nil [dot] [dot] [dot] [at] gmail [dot] com> wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 19 Jul 2011, at 18:08, marc wrote:
Winner.

On Tuesday, July 19, 2011 8:46:24 AM UTC-7, √iktor Klang wrote:
"Gimp my Library"

is this "gimp" in the sense of 

2.slang  a sexual fetishist who likes to be dominated and whodresses in a leather or rubber body suit with mask, zips, and chains
http://dictionary.reference.com/browse/gimp )


On Tue, Jul 19, 2011 at 5:24 PM, Josh Suereth <joshua [dot] [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Better to make a viral meme.   "Oh, don't do that, or implicit-cat will get you"


On Tue, Jul 19, 2011 at 10:53 AM, Nils Kilden-Pedersen <nil [dot] [dot] [dot] [at] gmail [dot] com> wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang

Social Web Architect
http://bblfish.net/
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A scala anti pattern -- looking for a name


On Tue, Jul 19, 2011 at 6:14 PM, Henry Story <henry [dot] story [at] gmail [dot] com> wrote:

On 19 Jul 2011, at 18:08, marc wrote:
Winner.

On Tuesday, July 19, 2011 8:46:24 AM UTC-7, √iktor Klang wrote:
"Gimp my Library"

is this "gimp" in the sense of 

2. slang  a sexual fetishist who likes to be dominated and whodresses in a leather or rubber body suit with mask, zips, and chains
http://dictionary.reference.com/browse/gimp )

You can pick your own definition ;-)




On Tue, Jul 19, 2011 at 5:24 PM, Josh Suereth <joshua [dot] [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Better to make a viral meme.   "Oh, don't do that, or implicit-cat will get you"


On Tue, Jul 19, 2011 at 10:53 AM, Nils Kilden-Pedersen <nil [dot] [dot] [dot] [at] gmail [dot] com> wrote:
On Tue, Jul 19, 2011 at 4:43 PM, Henry Story <henry [dot] [dot] [dot] [at] gmail [dot] com> wrote:
Good name. But certainly the "Pimpin Reto" anti-pattern, would do it's author a lot more credit though?

I'm not sure I'd want an anti-pattern named after me. Does the author?




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang

Social Web Architect
http://bblfish.net/



--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
reto 2
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Aw: Re: A scala anti pattern -- looking for a name
As I'm the person that according to Henry wants to have his name associated with an anti-pattern, I'm eager to understand what this anti-pattern is about.

Importing the members of an instance makes only sense when that instance has some instance fields (otherwise you could use an object). I think the import-statement can be quite nicely used to set a context. (The example of Henry is confusing as it calls b_ on a graph-instance, the EzGraph code is however designed to easily write down rdf graphs in scala, similarly to the turtle language it is designed for a single graph).

An example on how I think imports can be used to set the context:


val companyA : EzCompany = ..
val companyB : EzCompany = ...

val henry: Person = ..

import companyA._
henry.paySalary(); // The person is implicitly converted to a an Employe of companyA,
henry.fire();
henry.payServerancePackage()

import companyB._
henry.hire() // The person is implicitly converted to a an Employe of companyB
henry.paySalary(); //this calls transfers money from companyB to henry

The EzMGraph DSL to create RDF graphs in clerezza is similar

val uriA: UriRef
val uriB: UriRef
val uriC: UriRef
val uriD: UriRef

//here we add triples to ezGraphB
import ezGraphA._
//FOAF.knows and name are UriRefs, in RDF UriRefs are both property-types as well as nodes
uriA -- FOAF.knows --> uriB
uriB -- FOAF.name -->"Alice"

//here we add triples to ezGraphB
import ezGraphB._
uriA -- FOAF.knows --> uriC
uriC -- FOAF.knows --> uriD

assuming the two graphs were empty at the beginning they now have exactly two triples.


Reto
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Re: A scala anti pattern -- looking for a name
I'm still not sure why you need implicits here or what they add.
As for the company example, it's mildly terrifying to me.  How do I know someone works for a given company?  THe implicit conversion doesn't give me any assurances about that in the type system.  Maybe if all that info was encoded in the original type so it was guaranteed I couldn't pay employees from the wrong company, it'd be ok.
The style you're advocating for appears to be defeating type safety for a questionable readability gain.  I'd argue you could shuffle around methods and achieve the same power without the danger.
The idea of importing implicits from *specific instances* is not bad.  I love that idea when it comes to type classes.   However, there's safety here.  You can guarantee that those methods only apply for T's where T has a supporting type class (see the Numeric and Numeric#Ops traits).
- Josh

On Tue, Jul 19, 2011 at 1:27 PM, Reto Bachmann-Gmür <me [at] farewellutopia [dot] com> wrote:
As I'm the person that according to Henry wants to have his name associated with an anti-pattern, I'm eager to understand what this anti-pattern is about.

Importing the members of an instance makes only sense when that instance has some instance fields (otherwise you could use an object). I think the import-statement can be quite nicely used to set a context. (The example of Henry is confusing as it calls b_ on a graph-instance, the EzGraph code is however designed to easily write down rdf graphs in scala, similarly to the turtle language it is designed for a single graph).

An example on how I think imports can be used to set the context:


val companyA : EzCompany = ..
val companyB : EzCompany = ...

val henry: Person = ..

import companyA._
henry.paySalary(); // The person is implicitly converted to a an Employe of companyA,
henry.fire();
henry.payServerancePackage()

import companyB._
henry.hire() // The person is implicitly converted to a an Employe of companyB
henry.paySalary(); //this calls transfers money from companyB to henry

The EzMGraph DSL to create RDF graphs in clerezza is similar

val uriA: UriRef
val uriB: UriRef
val uriC: UriRef
val uriD: UriRef

//here we add triples to ezGraphB
import ezGraphA._
//FOAF.knows and name are UriRefs, in RDF UriRefs are both property-types as well as nodes
uriA -- FOAF.knows --> uriB
uriB -- FOAF.name -->"Alice"

//here we add triples to ezGraphB
import ezGraphB._
uriA -- FOAF.knows --> uriC
uriC -- FOAF.knows --> uriD

assuming the two graphs were empty at the beginning they now have exactly two triples.


Reto

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Re: A scala anti pattern -- looking for a name
It's an anti-pattern because context is very easy to overlook.  The push towards immutability is because the context of _what is the state now_ is hard to keep straight.  Mixing non-obvious implicit context with non-obvious mutable context is a recipe for error.  I'm not saying you should _never_ do it, but you should think very hard about whether there's some more robust way to express the same idea.

In your example, henry contains a bunch of mutable state.  You could at _least_ have the company explicitly named:

  henry.asEmployeeOf(companyA){ henry =>
    henry.paySalary()
    if (!henry.reviewCode) henry.fire()
  }

Saving a little typing while losing critical context cues is almost always the wrong thing to do.

  --Rex

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: A scala anti pattern -- looking for a name

"name shadowing 2.0"

Am 19.07.2011 20:27, schrieb Rex Kerr:
> It's an anti-pattern because context is very easy to overlook. The
> push towards immutability is because the context of _what is the state
> now_ is hard to keep straight. Mixing non-obvious implicit context
> with non-obvious mutable context is a recipe for error. I'm not
> saying you should _never_ do it, but you should think very hard about
> whether there's some more robust way to express the same idea.
>
> In your example, henry contains a bunch of mutable state. You could
> at _least_ have the company explicitly named:
>
> henry.asEmployeeOf(companyA){ henry =>
> henry.paySalary()
> if (!henry.reviewCode) henry.fire()
> }
>
> Saving a little typing while losing critical context cues is almost
> always the wrong thing to do.
>
> --Rex
>

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name

Whilst I think the whole thread is verging on offensive, I'd fully
understand if you were upset by it....

I do have to say this code scares me as its shown, seeing:

// join new company
val happyHenry : Employee = henry.joinCompany(companyA, startDate)
// leave old
henry.resign().hopeForServerancePackage()

val happierHenry : PaidEmployee = companyA.pay(happyHenry)

val upsetHenry : FiredEmployee = companyA.fire(happyHenry)

....

instead of

import companyA._
henry.paySalary(); // The person is implicitly converted to a an
Employe of companyA,
henry.fire();
henry.payServerancePackage()

is clearer and less risky even if it is more wordy.

The problem with that code is that if you // import companyA._, you
get a big oops occur. Or you have a higher precedence import
elsewhere --> oops.

I don't think this can be called an anti-pattern regardless, its got
to have been done more than a few times by different people to be any
kind of pattern.

Its not code I'd want to use but that doesn't seem to justify this
kind of public spectacle.

That said, I think you are taking this very well and should be
respected for that.

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name

On Tue, Jul 19, 2011 at 11:44 AM, Chris Twiner wrote:
> Whilst I think the whole thread is verging on offensive, I'd fully
> understand if you were upset by it....
>
> I do have to say this code scares me as its shown, seeing:
>
> // join new company
> val happyHenry : Employee = henry.joinCompany(companyA, startDate)
> // leave old
> henry.resign().hopeForServerancePackage()
>
> val happierHenry : PaidEmployee = companyA.pay(happyHenry)
>
> val upsetHenry : FiredEmployee = companyA.fire(happyHenry)
>
> ....
>
> instead of
>
> import companyA._
> henry.paySalary(); // The person is implicitly converted to a an
> Employe of companyA,
> henry.fire();
> henry.payServerancePackage()
>
> is clearer and less risky even if it is more wordy.
>
> The problem with that code is that if you // import companyA._, you
> get a big oops occur.  Or you have a higher precedence import
> elsewhere --> oops.
>
> I don't think this can be called an anti-pattern regardless, its got
> to have been done more than a few times by different people to be any
> kind of pattern.
>
> Its not code I'd want to use but that doesn't seem to justify this
> kind of public spectacle.
>
> That said, I think you are taking this very well and should be
> respected for that.

Reto wrote "I think it's important to identify anti-pattern. Post a
link here if you document the anti-pattern you think you've discovered
on the scala mailing list" and then, here, "I'm eager to understand
what this anti-pattern is about". He asked for a public *airing*, and
he's getting it. I don't think there's any "offense" or "spectacle" --
that might be the case if posters really were naming the anti-pattern
after him, but they aren't -- other than Henry, who obviously is
unhappy about his patch being rejected. Everyone should be paying
attention to http://en.wikipedia.org/wiki/Egoless_programming . And
there really is an anti-pattern here that has been identified --
excessive and improper use of implicits that discard type safety.

Maxime Lévesque
Joined: 2009-08-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name

I'd argue that there is a more generic anti pattern : Discarding Type Safety,
there are plenty to lose type safety. This being is a specific case of it,
does it deserve it's own anti pattern ?

2011/7/19 Jim Balter <Jim [at] balter [dot] name>
On Tue, Jul 19, 2011 at 11:44 AM, Chris Twiner <chris [dot] twiner [at] gmail [dot] com> wrote:
> Whilst I think the whole thread is verging on offensive, I'd fully
> understand if you were upset by it....
>
> I do have to say this code scares me as its shown, seeing:
>
> // join new company
> val happyHenry : Employee = henry.joinCompany(companyA, startDate)
> // leave old
> henry.resign().hopeForServerancePackage()
>
> val happierHenry : PaidEmployee = companyA.pay(happyHenry)
>
> val upsetHenry : FiredEmployee = companyA.fire(happyHenry)
>
> ....
>
> instead of
>
> import companyA._
> henry.paySalary(); // The person is implicitly converted to a an
> Employe of companyA,
> henry.fire();
> henry.payServerancePackage()
>
> is clearer and less risky even if it is more wordy.
>
> The problem with that code is that if you // import companyA._, you
> get a big oops occur.  Or you have a higher precedence import
> elsewhere --> oops.
>
> I don't think this can be called an anti-pattern regardless, its got
> to have been done more than a few times by different people to be any
> kind of pattern.
>
> Its not code I'd want to use but that doesn't seem to justify this
> kind of public spectacle.
>
> That said, I think you are taking this very well and should be
> respected for that.

Reto wrote "I think it's important to identify anti-pattern. Post a
link here if you document the anti-pattern you think you've discovered
on the scala mailing list" and then, here, "I'm eager to understand
what this anti-pattern is about". He asked for a public *airing*, and
he's getting it. I don't think there's any "offense" or "spectacle" --
that might be the case if posters really were naming the anti-pattern
after him, but they aren't -- other than Henry, who obviously is
unhappy about his patch being rejected. Everyone should be paying
attention to http://en.wikipedia.org/wiki/Egoless_programming . And
there really is an anti-pattern here that has been identified --
excessive and improper use of implicits that discard type safety.

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name

Yes, especially in the context of Scala ... a number of posters have
identified this as a specific problem, particularly among people new
to the language. And I really don't think "discarding type safety"
qualifies as a (anti-) pattern.

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Re: A scala anti pattern -- looking for a name
On Tue, Jul 19, 2011 at 4:27 PM, Jim Balter <Jim [at] balter [dot] name> wrote:
And
there really is an anti-pattern here that has been identified --
excessive and improper use of implicits that discard type safety.

Although the code is not type-safe, there are lots of other patterns that also are not type-safe and do not have this particular flaw.

The flaw here is _non-obvious context_.  It's not so much a problem with types as it is with _labels_.

Of course, there is a limit where one has no variable names, only types; all objects of the same type are the same.  But since that's not how most languages work, it's important to draw the distinction.

Look, we can rewrite the same pattern without sneaky imports of implicits:

    companyAize
    henry.doWhatever
    companyBize
    henry.doWhateverElse

where companyAize sets a mutable variable that's read by henry.doWhatever (likewise with B and doWhateverElse).

This is bad coding practice because it is hard to follow the state changes, especially as code gets more complex or needs to be added.

Doesn't matter whether it's a hidden global variable, a hidden mutable class member, or a hidden implicit parameter.  The problem is hidden yet varying context-sensitivity in each case.

  --Rex

Derek Chen-Becker 2
Joined: 2011-07-19,
User offline. Last seen 42 years 45 weeks ago.
Re: Aw: Re: A scala anti pattern -- looking for a name

As slick as this may appear at first, when someone mistakenly (or
ignorantly) removes an import statement then all hell breaks loose.

Implicits can be great when used *judiciously* to extend functionality
or "lubricate" the process of converting between two types (even then,
be careful), but this just appears to be trying to avoid a little extra
typing by making the context of the code itself implicit. There's plenty
of room to argue exactly where the right balance of conciseness and
readability lies, but to me the sample code you've shown here is just
setting its maintainers up for some nasty surprises.

Derek

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name

On Tue, Jul 19, 2011 at 2:26 PM, Rex Kerr wrote:
> On Tue, Jul 19, 2011 at 4:27 PM, Jim Balter wrote:
>>
>> And
>> there really is an anti-pattern here that has been identified --
>> excessive and improper use of implicits that discard type safety.
>
> Although the code is not type-safe, there are lots of other patterns that
> also are not type-safe and do not have this particular flaw.
>
> The flaw here is _non-obvious context_.  It's not so much a problem with
> types as it is with _labels_.
>
> Of course, there is a limit where one has no variable names, only types; all
> objects of the same type are the same.  But since that's not how most
> languages work, it's important to draw the distinction.
>
> Look, we can rewrite the same pattern without sneaky imports of implicits:
>
>     companyAize
>     henry.doWhatever
>     companyBize
>     henry.doWhateverElse
>
> where companyAize sets a mutable variable that's read by henry.doWhatever
> (likewise with B and doWhateverElse).
>
> This is bad coding practice because it is hard to follow the state changes,
> especially as code gets more complex or needs to be added.
>
> Doesn't matter whether it's a hidden global variable, a hidden mutable class
> member, or a hidden implicit parameter.  The problem is hidden yet varying
> context-sensitivity in each case.
>
>   --Rex

Yes, this looks like the correct identification. There may be a whole
set of problems that can result from promiscuous use of implicits, but
that too is not a pattern per se, whereas this is, and isn't limited
to Scala or implicits.

Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: A scala anti pattern -- looking for a name
And very importantly, with the patch I proposed on CLEREZZA-603  you don't need the implicits.
So instead of writing

val ez1: EZMGraph...
val ez2: EZMGraph...
import ez1._
ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri
import ez2._
ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
import ez1._
ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri

 You can write

val ez1: EZMGraph...
val ez2: EZMGraph...
ez1.b_("reto") -- FOAF.homepage --> "http://farewellutopic.com/".uri
ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri

 And it does the right thing. 

Perhaps I did not emphasize that enough in the bug report or the patch submission.







reto 2
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Aw: Re: Re: A scala anti pattern -- looking for a name
The person2employee example has the weakens you identify that there is no check (at least not enforced by type-checking at compile time) that the person is in fact an employee of the respective company. I think however that when writing utility classes one often has to weigh compile time checking against simplicity and uniformity of the API. In some cases the benefits of having a simple API might outweigh the disadvantage of the possibility of a runtime exception. I agree that the readability gain is questionable in general, in the concrete RDF-Graph example in my  mail I think the gain is quite big as it would otherwise be

EzGraphNode(uriA, graphA) -- FOAF.knows --> uriB
EzGraphNode(uriB, graphA) -- FOAF.name -->"Alice"
EzGraphNode(uriA, graphB) -- FOAF.knows --> uriC
EzGraphNode(uriC, graphB)  -- FOAF.knows --> uriD


The general idea I tried to show with the person2employee example is the dynamic applying of context specific decorators. Many different systems deal with Persons in different ways, decorators may offer this context specific methods.

E.g.:
Explicit variant:
val henryCath = new PersonAsSeenByRomanCatholicChurch(henry)
henryCatch.beatify() //thows AccessControlException if PopePermission missing

Implicit Variant:
import RomanCatholic._
henry.beatify()

If another decorator has a method with the same name, we might run into the situation which seems to be perceived as the problem justifying naming this an anti-pattern:

import RomanCatholic._
henry.baptise()

import Wicca._
henry.beatify()

import RomanCatholic._
henry.exCommunicate

Obviously without the "import Wicca._" statement something rather weird happens above. Personally I think this problem should be tacked by limiting the scopes of the imports, e.g. by adding braces around the 3 import scopes in the example rather than deprecating the pattern (calling it an anti-pattern).

Now to come back to the issue Henry original raised, the question is if methods of say PersonAsSeenByRomanCatholicChurch that return a person should rather return PersonAsSeenByRomanCatholicChurch or just Person. While returning a PersonAsSeenByRomanCatholicChurch may obsolete another implicit conversions I think its generally better to apply the decorator only when and if needed.

An example to illustrate desired changing of scope:

val heretics: Set[Person] = ...
heretics += henry

//lets add the whole wicca-enotourage of the heretic
import Wicca._
heretics += henry.bloodBrother
heretics += henry.godfather
heretics += henry.priest

import RomanCatholic._
for (h <- heretics) {
  h.excommunicate()
}

Above clearly we want to excommunicate from the roman catcholic church and not from Wicca, this works correctly if the Wicca-decorator methods bloodBrother, godfather and priest returned a Person and not a WiccaPerson, as otherwise WiccaPerson.excommunicate would be invoked.

Reto
Philippe Lhoste
Joined: 2010-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 19/07/2011 18:14, Henry Story wrote:
> ( http://dictionary.reference.com/browse/gimp )

Wow, I didn't know this word has so many senses!
I only knew the GNU Image Manipulation Program, which was probably the original sense of
this klangism (or at least the way I interpreted it).

reto 2
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Aw: Re: Aw: Re: A scala anti pattern -- looking for a name
Well the sample code is an ugly strawman, the idea of the DSL is to provide a language to write graphs in a similar way than in dedicated RDF serialization formats like Turtle. Calling the b_ method on an explicit instance clearly defeats this purpose.

Creating RDF-Graphs as anonymous subclasses

val ez1: MGraph = new EZMGraph() {(
  bnode -- FOAF.homepage --> "http://farewellutopic.com/".uri
      -- FOAF.currentProject --> "http://clerezza.org/".uri
)}


Which is a shortcut for
val ez1: MGraph = new SimpleMGraph() {(
  val bnode = new BNode()
  add(new TripmeImpl(bnode, FOAF.homepage, new UriRef("http://farewellutopic.com/"))
  add(new TripmeImpl(bnode, FOAF.curentProject, new UriRef("http://clerezza.org/"))
)}

While the example above wouldn't necessarily need implicit conversion as the bnode method of EzMGraph could return something like a RichBNode I see no good alternative to implicit conversions in case like in the example in my fisrt mail in this thread, or for example to allow the following code

// a graph with a single triple:
// foaf:Person rdf:type rdfs:Class
val simple: MGraph = new EZMGraph() {
  FOAF.Person a RDFS.Class
}

Reto

Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: Aw: Re: Re: A scala anti pattern -- looking for a name

On 20 Jul 2011, at 12:56, Reto Bachmann-Gmür wrote:
 In some cases the benefits of having a simple API might outweigh the disadvantage of the possibility of a runtime exception. I agree that the readability gain is questionable in general, in the concrete RDF-Graph example in my  mail I think the gain is quite big as it would otherwise be

EzGraphNode(uriA, graphA) -- FOAF.knows --> uriB
EzGraphNode(uriB, graphA) -- FOAF.name -->"Alice"
EzGraphNode(uriA, graphB) -- FOAF.knows --> uriC
EzGraphNode(uriC, graphB)  -- FOAF.knows --> uriD 

I have opened an issue for this problem Enable Ez wiring of chained statements without requiring imports of ez.and written a small patch that allows one to write instead of the above, the following
graphA2.node(uriA)  -- FOAF.knows --> ( uriB -- FOAF.name --> "Dan Brickley" )graphB2.node(uriA)  -- FOAF.knows --> ( uriC --  FOAF.knows --> uriD )

or even
val graphA3 = new EzMGraph() {	node(uriA)  -- FOAF.knows --> ( uriB -- FOAF.name --> "Dan Brickley" )}val graphB3 = new EzMGraph() {	node(uriA)  -- FOAF.knows --> ( uriC --  FOAF.knows --> uriD )}

Neither of those require imports of object instance prefixes between any two calls.In fact I removed the code allowing one to do that altogether from the bblfish branch of clerezza on github.
The patch is here:   https://github.com/bblfish/clerezza/commit/51be3b14a5488838d87094e81455ca806507b72b
The cost one has to pay is that one needs a few methods for EzMGraph, but I think it is a lot easierto understand. The idea of importing context through an object is very weird.

   Henry

[1] https://github.com/bblfish/clerezza/blob/zz-issues/parent/rdf.scala.utils/src/test/scala/org/apache/clerezza/rdf/scala/utils/EzMGraphTest.scala

PS. I am pretty sure the  "import ez._" left in the test code are no longer needed. I'll remove them from the github branch.


The general idea I tried to show with the person2employee example is the dynamic applying of context specific decorators. Many different systems deal with Persons in different ways, decorators may offer this context specific methods.

Social Web Architect
http://bblfish.net/
Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 20/07/11 00:26, Henry Story wrote:
> variable
>
Guys guys, chill out, I found the problem.

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: A scala anti pattern -- looking for a name


On Thu, Jul 21, 2011 at 11:29 AM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 20/07/11 00:26, Henry Story wrote:
> variable
>
Guys guys, chill out, I found the problem.

ROFL

 

- --
Tony Morris
http://tmorris.net/

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk4n8X8ACgkQmnpgrYe6r63BMACfUvY85kmlb07cMAPMfN1S1jcv
J8UAoJt2EjqTflb/m0FOMjgHKEp7QM0r
=p+hj
-----END PGP SIGNATURE-----




--
Viktor Klang

Akka Tech LeadTypesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang
reto 2
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: Aw: Re: Re: A scala anti pattern -- looking for a name

On Wed, Jul 20, 2011 at 4:10 PM, Henry Story wrote:
> val graphB3 = new EzMGraph() {
> node(uriA) -- FOAF.knows --> ( uriC -- FOAF.knows --> uriD )
> }

A few questions and comments to this proposal:

1. How comes you don't need to invoke node for uriC?

2. Is the -->-method overloaded to allow both wrapped and unwrapped
resources as argument?

3. to avoid the explicit node call a protected implicit method would
be enough, this wouldn't allow constructing the ugly strawman you
started the thread with, what's bad with this?

4. I think the required different handling of subject and object
defeats the goal of reaching similarity with dedicated
RDF-serialization formats: uri("http://bblfish.net/#hjs") --
FOAF.homePage --> "http://bblfish.net/#hjs".uri

Reto

Henry Story
Joined: 2011-03-26,
User offline. Last seen 42 years 45 weeks ago.
Re: A scala anti pattern -- looking for a name

On 21 Jul 2011, at 11:44, Reto Bachmann-Gmür wrote:

> On Wed, Jul 20, 2011 at 4:10 PM, Henry Story wrote:
>> val graphB3 = new EzMGraph() {
>> node(uriA) -- FOAF.knows --> ( uriC -- FOAF.knows --> uriD )
>> }
>
> A few questions and comments to this proposal:
>
> 1. How comes you don't need to invoke node for uriC?

In the previous commit [1] I added an implicit

implicit def resourceToRichGraphNode(res: Resource) = new RichGraphNode(res, new SimpleMGraph())

to the Preamble. That make senses, especially for cases outside of an EzMGraph.

But it is true that this is a bit clumsy. One would wish to also have resource inside an EzMGraph
automatically converted to RichGraphNodes with the Graph as the store. So I added a new patch [2] right
now

implicit def resourceToRichGraphNode = null
implicit def node(resource: Resource) = new RichGraphNode(resource,baseTc)

This cancels the general Preamble implicit as explained by Josh Suereth in his
presentation on implicits [3] slide 17, and it allows one to write something very cleanly

val graphA4 = new EzMGraph() {
uriA -- FOAF.knows --> ( uriB -- FOAF.name --> "Dan Brickley" )
}

Now of course one is what you had initially.

It is close to what I was calling the anti-pattern. Because it is possible from there on to call

export graphA4.node

One could perhaps protect that implicit so it is only seen by subclasses.

> 2. Is the -->-method overloaded to allow both wrapped and unwrapped
> resources as argument?

It allows both a resource and a RichGraphNode. That code has not changed as
and can be seen on github. In the example above it takes a GraphNode, and with the
implicit it does indeed give it the same graph as the containing EzMGraph (I think)

https://github.com/bblfish/clerezza/blob/560bc117b5ae38151aa53205f51743d...

>
> 3. to avoid the explicit node call a protected implicit method would
> be enough, this wouldn't allow constructing the ugly strawman you
> started the thread with, what's bad with this?

yes. That is what I was coming to the conclusion of.

The implicit inside the class seems to work, and it could be protected.
As shown above it seems to be possible to have a local implicit that uses the local tcgraph,
and a more generic implicit that would work outside of the graph context by constructing a
mutable graph.

>
> 4. I think the required different handling of subject and object
> defeats the goal of reaching similarity with dedicated
> RDF-serialization formats: uri("http://bblfish.net/#hjs") --
> FOAF.homePage --> "http://bblfish.net/#hjs".uri

You mean .uri and uri() ?
Yes, that's another issue. I am not religious about it. Other things I had thought of
was an

object uri { def apply(uriStr: Uri) = new UriRef(uriStr) }

-----

Anyway, it is true that a graph of statements is very close to what in Scala one would
have inside a { ... }. It is a context for writing something. Within such a context one
can argue that any other context that appears needs to be placed inside its own { }.
So perhaps the import ez.node is not such an impossible thing.

But at the same time one should perhaps not be forcing that either on the user. Because there
may well be cases where one is filtering statements into various graphs, and so be working
with many simultaneously.

Ideally one would wish this to be quite explicit with someting like

graph g { a -- rel --> b
-- re2 --> ( bnode -- re3 --> something )
}

Subclassing the graph seems to come closest to that.

Henry

>
> Reto

[1] https://github.com/bblfish/clerezza/commit/51be3b14a5488838d87094e81455c...
[2] https://github.com/bblfish/clerezza/commit/560bc117b5ae38151aa53205f5174...
[3] http://scala-lift.blogspot.com/2011/03/josh-suereth-on-implicits-without...
I have not yet finished watching, so I may still discover all kinds of things.

Social Web Architect
http://bblfish.net/

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