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

Implicit CallSiteInfo objects?

15 replies
Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.

Hello list,

I was just thinking about logging and I thought that some kind of
compiler magic could do wonders. If there was some mechanism similar
to manifests that provided a CallSiteInfo object for you, which
contains information like source file name, line number, calling
method and the type containing the calling method, that would come
quite handy.

Usage would be something like this:

trait Logging {
def log(msg: String)(implicit csi: CallSiteInfo) =
printline(csi.sourceFileName + " " + csi.lineNumber + ": " + msg)
}

object Main {

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Implicit CallSiteInfo objects?

Sorry, sent the mail too early. So again:

I was just thinking about logging and I thought that some kind of
compiler magic could do wonders. If there was some mechanism similar
to manifests that provided a CallSiteInfo object for you, which
contains information like source file name, line number, calling
method and the type containing the calling method, that would come
quite handy.

Usage would be something like this:

trait Logging {
def log(msg: String)(implicit csi: CallSiteInfo) =
printline(csi.sourceFileName + " line " + csi.lineNumber + ": " + msg)
}

object Main extends Logging {
def main(args: Array[String]) {
log("Hello World")
}
}

Would produce some output like:
Main.scala line 3: Hello World

Perhaps there are other applications for this besides logging?

Just dreaming... :-)

Regards,
Ruediger

imaier
Joined: 2008-07-01,
User offline. Last seen 23 weeks 2 days ago.
Re: Re: Implicit CallSiteInfo objects?

You can do something similar right now:

object A {
def main(args: Array[String]) {
log()
}

def log() = println(Thread.currentThread.getStackTrace()(2))
}

It's a little fragile though, since slight changes in the call stack can
invalidate your index into the stack trace. Think of closures and
indirections introduced by scalac.

Cheers,
Ingo

On 5/22/10 10:51 AM, Rüdiger Keller wrote:
> Sorry, sent the mail too early. So again:
>
>
> I was just thinking about logging and I thought that some kind of
> compiler magic could do wonders. If there was some mechanism similar
> to manifests that provided a CallSiteInfo object for you, which
> contains information like source file name, line number, calling
> method and the type containing the calling method, that would come
> quite handy.
>
> Usage would be something like this:
>
> trait Logging {
> def log(msg: String)(implicit csi: CallSiteInfo) =
> printline(csi.sourceFileName + " line " + csi.lineNumber + ": " + msg)
> }
>
> object Main extends Logging {
> def main(args: Array[String]) {
> log("Hello World")
> }
> }
>
> Would produce some output like:
> Main.scala line 3: Hello World
>
> Perhaps there are other applications for this besides logging?
>
> Just dreaming... :-)
>
> Regards,
> Ruediger
>

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Implicit CallSiteInfo objects?

The idea was exactly to replace the stack trace approach, seems it
forgot to mention in my mail. :-)

Using the stack trace has severe performance implications and it does
not provide all the information that a CallSiteInfo object could
provide, much less in a type safe manner.

Regards,
Ruediger

2010/5/22 Ingo Maier :
> You can do something similar right now:
>
> object A {
>  def main(args: Array[String]) {
>    log()
>  }
>
>  def log() = println(Thread.currentThread.getStackTrace()(2))
> }
>
> It's a little fragile though, since slight changes in the call stack can
> invalidate your index into the stack trace. Think of closures and
> indirections introduced by scalac.
>
> Cheers,
> Ingo
>
> On 5/22/10 10:51 AM, Rüdiger Keller wrote:
>>
>> Sorry, sent the mail too early. So again:
>>
>>
>> I was just thinking about logging and I thought that some kind of
>> compiler magic could do wonders. If there was some mechanism similar
>> to manifests that provided a CallSiteInfo object for you, which
>> contains information like source file name, line number, calling
>> method and the type containing the calling method, that would come
>> quite handy.
>>
>> Usage would be something like this:
>>
>> trait Logging {
>>   def log(msg: String)(implicit csi: CallSiteInfo) =
>> printline(csi.sourceFileName + " line " + csi.lineNumber + ": " + msg)
>> }
>>
>> object Main extends Logging {
>>        def main(args: Array[String]) {
>>                log("Hello World")
>>        }
>> }
>>
>> Would produce some output like:
>> Main.scala line 3: Hello World
>>
>> Perhaps there are other applications for this besides logging?
>>
>> Just dreaming... :-)
>>
>> Regards,
>> Ruediger
>>
>
>

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Implicit CallSiteInfo objects?

and you'd be able to write extremely confusing code by using conditions
like if (comeFrom(class, method, line))
who wouldn't want that?

for logging, it would be quiter useful, i agree. but for nothing else.

Rüdiger Keller schrieb:
> Hello list,
>
> I was just thinking about logging and I thought that some kind of
> compiler magic could do wonders. If there was some mechanism similar
> to manifests that provided a CallSiteInfo object for you, which
> contains information like source file name, line number, calling
> method and the type containing the calling method, that would come
> quite handy.
>
> Usage would be something like this:
>
> trait Logging {
> def log(msg: String)(implicit csi: CallSiteInfo) =
> printline(csi.sourceFileName + " " + csi.lineNumber + ": " + msg)
> }
>
> object Main {
>
>

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Implicit CallSiteInfo objects?

Ah, funny idea.

But actually that resembles aspect oriented programming a lot.

Regards,
Ruediger

2010/5/22 HamsterofDeath :
> and you'd be able to write extremely confusing code by using conditions
> like if (comeFrom(class, method, line))
> who wouldn't want that?
>
> for logging, it would be quiter useful, i agree. but for nothing else.
>
> Rüdiger Keller schrieb:
>> Hello list,
>>
>> I was just thinking about logging and I thought that some kind of
>> compiler magic could do wonders. If there was some mechanism similar
>> to manifests that provided a CallSiteInfo object for you, which
>> contains information like source file name, line number, calling
>> method and the type containing the calling method, that would come
>> quite handy.
>>
>> Usage would be something like this:
>>
>> trait Logging {
>>    def log(msg: String)(implicit csi: CallSiteInfo) =
>> printline(csi.sourceFileName + " " + csi.lineNumber + ": " + msg)
>> }
>>
>> object Main {
>>
>>
>
>

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Implicit CallSiteInfo objects?

Ok, thinking about it for a second, it probably does NOT resemble
aspect oriented programming a whole lot. :-)

Regards,
Ruediger

2010/5/22 Rüdiger Keller :
> Ah, funny idea.
>
> But actually that resembles aspect oriented programming a lot.
>
> Regards,
> Ruediger
>
>
> 2010/5/22 HamsterofDeath :
>> and you'd be able to write extremely confusing code by using conditions
>> like if (comeFrom(class, method, line))
>> who wouldn't want that?
>>
>> for logging, it would be quiter useful, i agree. but for nothing else.
>>
>> Rüdiger Keller schrieb:
>>> Hello list,
>>>
>>> I was just thinking about logging and I thought that some kind of
>>> compiler magic could do wonders. If there was some mechanism similar
>>> to manifests that provided a CallSiteInfo object for you, which
>>> contains information like source file name, line number, calling
>>> method and the type containing the calling method, that would come
>>> quite handy.
>>>
>>> Usage would be something like this:
>>>
>>> trait Logging {
>>>    def log(msg: String)(implicit csi: CallSiteInfo) =
>>> printline(csi.sourceFileName + " " + csi.lineNumber + ": " + msg)
>>> }
>>>
>>> object Main {
>>>
>>>
>>
>>
>

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Implicit CallSiteInfo objects?

It's an interesting idea. I've pondered something similar to reflect
on the current method, exposing it's name, the parameter names and
tupled arguments.

Using implicit parameters to inject this information seems appealing
at first, but what should be passed as the parameter `csi2` in this
case?

def foo(implicit csi1: CallSiteInfo) = bar
def bar(implicit csi2: CallSiteInfo) = csi.caller

Normal implicit rules would pass the in scope value `csi1`, but this
probably isn't what you want. Manifests don't suffer this problem, as
they are parameterized by a type.

I keep hearing about an in-development reflection library for a future
version of Scala, perhaps it will help out.

-jason

On Sat, May 22, 2010 at 10:45 AM, Rüdiger Keller
wrote:
> Hello list,
>
> I was just thinking about logging and I thought that some kind of
> compiler magic could do wonders. If there was some mechanism similar
> to manifests that provided a CallSiteInfo object for you, which
> contains information like source file name, line number, calling
> method and the type containing the calling method, that would come
> quite handy.

Rüdiger Keller
Joined: 2010-01-24,
User offline. Last seen 42 years 45 weeks ago.
Re: Implicit CallSiteInfo objects?

Indeed, that's kind of a problem. CSIs would require special handling,
because passing along CSIs probably wouldn't be desirable.

Another reason why they will probably never be included in Scala. ;-)

I also heard several times now, that some Scala reflection library is
in the works. Does anybody know some details?

Regards,
Ruediger

2010/5/22 Jason Zaugg :
> It's an interesting idea. I've pondered something similar to reflect
> on the current method, exposing it's name, the parameter names and
> tupled arguments.
>
> Using implicit parameters to inject this information seems appealing
> at first, but what should be passed as the parameter `csi2` in this
> case?
>
>  def foo(implicit csi1: CallSiteInfo) = bar
>  def bar(implicit csi2: CallSiteInfo) = csi.caller
>
> Normal implicit rules would pass the in scope value `csi1`, but this
> probably isn't what you want. Manifests don't suffer this problem, as
> they are parameterized by a type.
>
> I keep hearing about an in-development reflection library for a future
> version of Scala, perhaps it will help out.
>
> -jason
>
> On Sat, May 22, 2010 at 10:45 AM, Rüdiger Keller
> wrote:
>> Hello list,
>>
>> I was just thinking about logging and I thought that some kind of
>> compiler magic could do wonders. If there was some mechanism similar
>> to manifests that provided a CallSiteInfo object for you, which
>> contains information like source file name, line number, calling
>> method and the type containing the calling method, that would come
>> quite handy.
>

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
why doesn't option offer a "contains"-method?

in my code, i did this quite a few times:
if (op.isdefined && op.get==myObj) { // or op.isDefined &&
certainCondition(op.get)
doSomething()
}

contains(x) or isTrue(x => conditionOf(x)) would be shorter

and while i'm at it, i invented this implicit def:
def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
if (o.isDefined) {
ifDefined(o.get)
} else {
ifEmpty
}
}

you can use it like this:

op ? (_.doit())
or
op ? (_.size, 0)

which is singificantly shorter than
if (op.isDefined) {op.get.doIt()} else {...}

Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: why doesn't option offer a "contains"-method?


On Mon, May 24, 2010 at 5:02 PM, HamsterofDeath <h-star [at] gmx [dot] de> wrote:
in my code, i did this quite a few times:
if (op.isdefined && op.get==myObj) { // or op.isDefined &&
certainCondition(op.get)
  doSomething()
}

contains(x) or isTrue(x => conditionOf(x)) would be shorter

contains(x) or isTrue(conditionOf(_)) would be shorter


and while i'm at it, i invented this implicit def:
 def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
   if (o.isDefined) {
     ifDefined(o.get)
   } else {
     ifEmpty
   }
 }

I think I'd implement it as:

o.map(ifDefined).getOrElse(ifEmpty)
 

you can use it like this:

op ? (_.doit())
or
op ? (_.size, 0)

which is singificantly shorter than
if (op.isDefined) {op.get.doIt()} else {...}

--
Viktor Klang
| "A complex system that works is invariably
| found to have evolved from a simple system
| that worked." - John Gall

Akka - the Actor Kernel: Akkasource.org
Twttr: twitter.com/viktorklang
ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: why doesn't option offer a "contains"-method?
I find
  for (i <- x if (condition)) { doSomething }
and
  x match { case Some("value") => doSomething ; case _ => }
and
  x filter (i => condition(i)) foreach (i => doSomething(i))
sufficiently short that i don't miss contains.

  --Rex

On Mon, May 24, 2010 at 11:02 AM, HamsterofDeath <h-star [at] gmx [dot] de> wrote:
in my code, i did this quite a few times:
if (op.isdefined && op.get==myObj) { // or op.isDefined &&
certainCondition(op.get)
  doSomething()
}

contains(x) or isTrue(x => conditionOf(x)) would be shorter

and while i'm at it, i invented this implicit def:
 def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
   if (o.isDefined) {
     ifDefined(o.get)
   } else {
     ifEmpty
   }
 }

you can use it like this:

op ? (_.doit())
or
op ? (_.size, 0)

which is singificantly shorter than
if (op.isDefined) {op.get.doIt()} else {...}



H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: why doesn't option offer a "contains"-method?

short yes, but this is just a "contains by side effect". i prefer to do
stuff explicitly instead of building an algorithm to replace a missing
method call

Rex Kerr schrieb:
> I find
> for (i <- x if (condition)) { doSomething }
> and
> x match { case Some("value") => doSomething ; case _ => }
> and
> x filter (i => condition(i)) foreach (i => doSomething(i))
> sufficiently short that i don't miss contains.
>
> --Rex
>
> On Mon, May 24, 2010 at 11:02 AM, HamsterofDeath > wrote:
>
> in my code, i did this quite a few times:
> if (op.isdefined && op.get==myObj) { // or op.isDefined &&
> certainCondition(op.get)
> doSomething()
> }
>
> contains(x) or isTrue(x => conditionOf(x)) would be shorter
>
> and while i'm at it, i invented this implicit def:
> def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
> if (o.isDefined) {
> ifDefined(o.get)
> } else {
> ifEmpty
> }
> }
>
> you can use it like this:
>
> op ? (_.doit())
> or
> op ? (_.size, 0)
>
> which is singificantly shorter than
> if (op.isDefined) {op.get.doIt()} else {...}
>
>
>

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: why doesn't option offer a "contains"-method?

Seems as good a time as any to direct folks to Tony's "Scala Option
Cheat Sheet" [1], and his exercises using the Option catamorphism,
which is what you've proposed with `def ?`.

-jason

[1] http://blog.tmorris.net/scalaoption-cheat-sheet/
[2] http://blog.tmorris.net/debut-with-a-catamorphism/

On Mon, May 24, 2010 at 5:02 PM, HamsterofDeath wrote:
> in my code, i did this quite a few times:
> if (op.isdefined && op.get==myObj) { // or op.isDefined &&
> certainCondition(op.get)
>   doSomething()
> }
>
> contains(x) or isTrue(x => conditionOf(x)) would be shorter

This one is actually interesting, it's the catamorphism across the
Option data type.

> and while i'm at it, i invented this implicit def:
>  def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
>    if (o.isDefined) {
>      ifDefined(o.get)
>    } else {
>      ifEmpty
>    }
>  }
>
> you can use it like this:
>
> op ? (_.doit())
> or
> op ? (_.size, 0)
>
> which is singificantly shorter than
> if (op.isDefined) {op.get.doIt()} else {...}

Kevin Wright
Joined: 2009-06-09,
User offline. Last seen 49 weeks 3 days ago.
Re: why doesn't option offer a "contains"-method?
Don't forget (in 2.8)
x collect {case Some("value") => doSomething()}
Though I'm not sure I like seeing side-effects in map/flatmap/filter/...

On 24 May 2010 16:31, Rex Kerr <ichoran [at] gmail [dot] com> wrote:
I find
  for (i <- x if (condition)) { doSomething }
and
  x match { case Some("value") => doSomething ; case _ => }
and
  x filter (i => condition(i)) foreach (i => doSomething(i))
sufficiently short that i don't miss contains.

  --Rex

On Mon, May 24, 2010 at 11:02 AM, HamsterofDeath <h-star [at] gmx [dot] de> wrote:
in my code, i did this quite a few times:
if (op.isdefined && op.get==myObj) { // or op.isDefined &&
certainCondition(op.get)
  doSomething()
}

contains(x) or isTrue(x => conditionOf(x)) would be shorter

and while i'm at it, i invented this implicit def:
 def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
   if (o.isDefined) {
     ifDefined(o.get)
   } else {
     ifEmpty
   }
 }

you can use it like this:

op ? (_.doit())
or
op ? (_.size, 0)

which is singificantly shorter than
if (op.isDefined) {op.get.doIt()} else {...}






--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda

Patrik Andersson
Joined: 2009-11-16,
User offline. Last seen 42 years 45 weeks ago.
Re: why doesn't option offer a "contains"-method?
No way similar to doing liftM ? (Although I admit, what you have here is virtually as short)

On Mon, May 24, 2010 at 6:38 PM, Kevin Wright <kev [dot] lee [dot] wright [at] googlemail [dot] com> wrote:
Don't forget (in 2.8)
x collect {case Some("value") => doSomething()}
Though I'm not sure I like seeing side-effects in map/flatmap/filter/...

On 24 May 2010 16:31, Rex Kerr <ichoran [at] gmail [dot] com> wrote:
I find
  for (i <- x if (condition)) { doSomething }
and
  x match { case Some("value") => doSomething ; case _ => }
and
  x filter (i => condition(i)) foreach (i => doSomething(i))
sufficiently short that i don't miss contains.

  --Rex

On Mon, May 24, 2010 at 11:02 AM, HamsterofDeath <h-star [at] gmx [dot] de> wrote:
in my code, i did this quite a few times:
if (op.isdefined && op.get==myObj) { // or op.isDefined &&
certainCondition(op.get)
  doSomething()
}

contains(x) or isTrue(x => conditionOf(x)) would be shorter

and while i'm at it, i invented this implicit def:
 def ?[X](ifDefined: (T) => X, ifEmpty: X = null) = {
   if (o.isDefined) {
     ifDefined(o.get)
   } else {
     ifEmpty
   }
 }

you can use it like this:

op ? (_.doit())
or
op ? (_.size, 0)

which is singificantly shorter than
if (op.isDefined) {op.get.doIt()} else {...}






--
Kevin Wright

mail/google talk: kev [dot] lee [dot] wright [at] googlemail [dot] com
wave: kev [dot] lee [dot] wright [at] googlewave [dot] com
skype: kev.lee.wright
twitter: @thecoda


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