www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Languages for servers (Go, D, and more)

reply "bearophile" <bearophileHUGS lycos.com> writes:
Go (compared to several other languages) for servers:

http://togototo.wordpress.com/2014/07/04/why-go-is-great-for-servers/

http://www.reddit.com/r/programming/comments/29t3zy/why_go_is_great_for_servers/

The two comments about D:

I considered an implementation in D, but while D has green 
threads in the form of fibres, but doesn’t seem to include a 
scheduler, so I’d have to write one myself. Also, while it has 
message passing between threads, it doesn’t seem to have message 
passing between fibres. It also has no equivalent of Go’s select 
statement, so the only way to poll multiple channels would be to 
wait on one with a very short timeout, then wait on the next, 
and so on in a loop, which is rather ugly.

D: y u no distinguish between ints/longs/floats/doubles and 
pointers when taking out the trash? You argue that internal 
pointers make implementing a precise garbage collector (which 
wouldn’t mistake numbers for pointers) impossible, but Go 
managed it in spite of also having internal pointers.

Bye, bearophile
Jul 04 2014
next sibling parent reply "Brian Rogoff" <brogoff gmail.com> writes:
On Friday, 4 July 2014 at 14:10:29 UTC, bearophile wrote:
D: y u no distinguish between ints/longs/floats/doubles and 
pointers when taking out the trash? You argue that internal 
pointers make implementing a precise garbage collector (which 
wouldn’t mistake numbers for pointers) impossible, but Go 
managed it in spite of also having internal pointers.


It is true that a precise (and moving) GC is desirable for long running servers, and that the Go GC has been receiving a lot of love; it's now stack precise with Go 1.3. I don't recall anyone arguing that internal pointers make a precise GC impossible. But there are plenty of D features that complicate a precise GC, amongst them internal pointers. IMO, the D story around GC is currently one of the weaker parts of the language. Sure, there are workarounds, including not using the GC at all, but then so many features are tied to it that the interested developer may just decide to use a language with a more mature and precise GC, like Java or Go, or none at all like C.
Jul 04 2014
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
05-Jul-2014 00:25, Chris Cain пишет:
 On Friday, 4 July 2014 at 19:46:40 UTC, Remo wrote:
 Who want to use C-style memory management today ?
 How about C++ style memory management, is this easy to this in D2
 now ?

The big problem with that is "C++ style memory management" implies we're going to have new/delete which AFAIK delete is depreciated and new is currently hardcoded to use the GC.

and RAII in general. C++'s 'new' and 'delete' are not much more then malloc/free repainted in pink (barring placement new, overloading). D has had support for RAII for a long time, the only problem is interaction with GC. Say in closures that contain structs with destructors, the latter do not have their destructors run and because the closure leaves in GC heap. -- Dmitry Olshansky
Jul 04 2014
prev sibling next sibling parent "Meta" <jared771 gmail.com> writes:
On Friday, 4 July 2014 at 15:29:06 UTC, Brian Rogoff wrote:
 On Friday, 4 July 2014 at 14:10:29 UTC, bearophile wrote:
D: y u no distinguish between ints/longs/floats/doubles and 
pointers when taking out the trash? You argue that internal 
pointers make implementing a precise garbage collector (which 
wouldn’t mistake numbers for pointers) impossible, but Go 
managed it in spite of also having internal pointers.


It is true that a precise (and moving) GC is desirable for long running servers, and that the Go GC has been receiving a lot of love; it's now stack precise with Go 1.3. I don't recall anyone arguing that internal pointers make a precise GC impossible. But there are plenty of D features that complicate a precise GC, amongst them internal pointers. IMO, the D story around GC is currently one of the weaker parts of the language. Sure, there are workarounds, including not using the GC at all, but then so many features are tied to it that the interested developer may just decide to use a language with a more mature and precise GC, like Java or Go, or none at all like C.

With nogc and the -vgc compiler switch, I think it would fairly easy now to do C-style memory management and know that there are no hidden GC allocations in your program. Whether you would want to do this in D is another story.
Jul 04 2014
prev sibling next sibling parent "Remo" <remo4d gmail.com> writes:
On Friday, 4 July 2014 at 16:16:35 UTC, Meta wrote:
 On Friday, 4 July 2014 at 15:29:06 UTC, Brian Rogoff wrote:
 On Friday, 4 July 2014 at 14:10:29 UTC, bearophile wrote:
D: y u no distinguish between ints/longs/floats/doubles and 
pointers when taking out the trash? You argue that internal 
pointers make implementing a precise garbage collector (which 
wouldn’t mistake numbers for pointers) impossible, but Go 
managed it in spite of also having internal pointers.


It is true that a precise (and moving) GC is desirable for long running servers, and that the Go GC has been receiving a lot of love; it's now stack precise with Go 1.3. I don't recall anyone arguing that internal pointers make a precise GC impossible. But there are plenty of D features that complicate a precise GC, amongst them internal pointers. IMO, the D story around GC is currently one of the weaker parts of the language. Sure, there are workarounds, including not using the GC at all, but then so many features are tied to it that the interested developer may just decide to use a language with a more mature and precise GC, like Java or Go, or none at all like C.

With nogc and the -vgc compiler switch, I think it would fairly easy now to do C-style memory management and know that there are no hidden GC allocations in your program. Whether you would want to do this in D is another story.

Who want to use C-style memory management today ? How about C++ style memory management, is this easy to this in D2 now ? IMHO nogc is the right direction. But it would be great if one could compile at least this code. int main(string[] argv) nogc { writeln("Hello D-World!"); return 0; }
Jul 04 2014
prev sibling next sibling parent "Chris Cain" <zshazz gmail.com> writes:
On Friday, 4 July 2014 at 19:46:40 UTC, Remo wrote:
 Who want to use C-style memory management today ?
 How about C++ style memory management, is this easy to this in 
 D2
 now ?

The big problem with that is "C++ style memory management" implies we're going to have new/delete which AFAIK delete is depreciated and new is currently hardcoded to use the GC. But malloc/free works, so C-style memory management is already here.
 IMHO  nogc is the right direction.

 But it would be great if one could compile at least this code.
 int main(string[] argv)  nogc {
    writeln("Hello D-World!");
    return 0;
 }

I'm sure we'll get there. There's some decent ground to cover before we can get that, though. We need to make it so phobos code doesn't need to allocate exceptions everywhere first (which should be doable). Plus we'll also need to keep having exceptions that have good error messages. I've posted a "proof of concept" of such a thing in the IRC, but here it is as well (obviously, it's really rough because I'm just throwing ideas together in a blender at this point...): https://gist.github.com/Zshazz/47ed52c3246e5348062a I'm also working on a few helpers for nogc code that'll make the above more concise and readable (again, *very* preliminary ... SemiStackSink is a mixin template in here, but that's only because I was trying out weird ideas; as it stands now it should just be a simple template struct): https://gist.github.com/Zshazz/fed0400674f034e09495 As a bonus, SemiStackSink working on 200_000_000 chars takes around 1/6 of the time as a pure GC implementation. Obviously for very small numbers of chars (<60), it's basically instant because it allocates on the stack at that point. So yeah, 2.066 will probably spur more work in code that doesn't need the GC. Once std.allocator lands and we start developing usage patterns on that, the amount of code that needs the GC will shrink even further.
Jul 04 2014
prev sibling next sibling parent "Chris Cain" <zshazz gmail.com> writes:
On Friday, 4 July 2014 at 20:25:24 UTC, Chris Cain wrote:
 depreciated

deprecated*. I swear I say it correctly and when I'm coding I type it correctly there XD
Jul 04 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Friday, 4 July 2014 at 20:25:24 UTC, Chris Cain wrote:
 On Friday, 4 July 2014 at 19:46:40 UTC, Remo wrote:
 Who want to use C-style memory management today ?
 How about C++ style memory management, is this easy to this in 
 D2
 now ?

The big problem with that is "C++ style memory management" implies we're going to have new/delete which AFAIK delete is depreciated and new is currently hardcoded to use the GC.

It does not matter at all - new/delete does not have anything that malloc/free don't give you. What does matter is that RAII does not fit will with some of language feature - for example, structs are not polymorphic so wrapping class into struct for RAII removes any polymorphic traits from it.
Jul 04 2014
prev sibling next sibling parent "Remo" <remo4d gmail.com> writes:
On Friday, 4 July 2014 at 20:43:01 UTC, Dicebot wrote:
 On Friday, 4 July 2014 at 20:25:24 UTC, Chris Cain wrote:
 On Friday, 4 July 2014 at 19:46:40 UTC, Remo wrote:
 Who want to use C-style memory management today ?
 How about C++ style memory management, is this easy to this 
 in D2
 now ?

The big problem with that is "C++ style memory management" implies we're going to have new/delete which AFAIK delete is depreciated and new is currently hardcoded to use the GC.

It does not matter at all - new/delete does not have anything that malloc/free don't give you. What does matter is that RAII does not fit will with some of language feature - for example, structs are not polymorphic so wrapping class into struct for RAII removes any polymorphic traits from it.

By "C++ style memory management" I do not mean naked new/delete or malloc/free. What I mean is RAII, smart pointers and destructor's. What is the proper replacement for std::unique_ptr and std::shared_ptr in D2 ? Of course with move support for unique_ptr :)
Jul 04 2014
prev sibling next sibling parent "Chris Cain" <zshazz gmail.com> writes:
On Friday, 4 July 2014 at 21:09:05 UTC, Remo wrote:
 By "C++ style memory management" I do not mean naked new/delete 
 or malloc/free.
 What I mean is RAII, smart pointers and destructor's.
 What is the proper replacement for std::unique_ptr and 
 std::shared_ptr in D2 ?
 Of course with move support for unique_ptr :)

Ah, I see what you mean now. D has that: http://dlang.org/phobos/std_typecons.html#.Unique http://dlang.org/phobos/std_typecons.html#.RefCounted But they probably need some decent updating for use with nogc and more modern D style, though. Also the Unique pointer also works with std.algorithm.move (in addition to its "release" method which could be deprecated, I think... not sure why it needs it when we have std.algorithm.move).
Jul 04 2014
prev sibling next sibling parent Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Fri, 2014-07-04 at 20:25 +0000, Chris Cain via Digitalmars-d wrote:
[=E2=80=A6]
 The big problem with that is "C++ style memory management"=20
 implies we're going to have new/delete which AFAIK delete is=20
 depreciated and new is currently hardcoded to use the GC.

All the C++ folk are saying that with C++14 is you are using any heap at all you are more than likely doing it wrong. Modern C++ idiom is for completely new/delete free code. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jul 04 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Chris Cain:

 http://dlang.org/phobos/std_typecons.html#.Unique

I'd like to read a little tutorial for the usage of that Unuque in D. Bye, bearophile
Jul 05 2014
prev sibling next sibling parent "ponce" <contact gam3sfrommars.fr> writes:
On Saturday, 5 July 2014 at 06:43:31 UTC, Russel Winder via 
Digitalmars-d wrote:
 All the C++ folk are saying that with C++14 is you are using 
 any heap at
 all you are more than likely doing it wrong. Modern C++ idiom 
 is for
 completely new/delete free code.

Minor nitpick, it is indeed devoid of "delete". But in modern C++ but the _heap_ is still used an awful lot, everytime a std::vector is copied, everytime a std::string is concatenated, etc. And it's very much silent. Modern C++ is a style that makes resource release timely and painless, but still let a lot of allocations go unchecked.
Jul 05 2014
prev sibling next sibling parent Russel Winder via Digitalmars-d <digitalmars-d puremagic.com> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Sat, 2014-07-05 at 11:46 +0000, ponce via Digitalmars-d wrote:
 On Saturday, 5 July 2014 at 06:43:31 UTC, Russel Winder via=20
 Digitalmars-d wrote:
 All the C++ folk are saying that with C++14 is you are using=20
 any heap at
 all you are more than likely doing it wrong. Modern C++ idiom=20
 is for
 completely new/delete free code.

Minor nitpick, it is indeed devoid of "delete". But in modern C++ but the _heap_ is still used an awful lot,=20 everytime a std::vector is copied, everytime a std::string is=20 concatenated, etc. And it's very much silent. Modern C++ is a=20 style that makes resource release timely and painless, but still=20 let a lot of allocations go unchecked.

Not a minor nitpick, an error on my part: I should have included the term "explicitly". Thanks for picking me up on this. As others have pointed out in the interim, modern C++ still uses unique_ptr, etc. and RAII so there is heap use, just no unconstrained use. --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Jul 05 2014
prev sibling next sibling parent "Brian Rogoff" <brogoff gmail.com> writes:
On Friday, 4 July 2014 at 19:46:40 UTC, Remo wrote:
 On Friday, 4 July 2014 at 16:16:35 UTC, Meta wrote:
 With  nogc and the -vgc compiler switch, I think it would 
 fairly easy now to do C-style memory management and know that 
 there are no hidden GC allocations in your program. Whether 
 you would want to do this in D is another story.

Who want to use C-style memory management today ?

Lots of interesting programs and libraries are written specifically in C, not C++, even today. But, as others have pointed out, you can use RAII in D and as time goes on even more advanced memory management libraries will become available. But my point was merely that D is somewhat hamstrung by virtue of being a garbage collected language with a not so great GC, and some complexities around not using it. Not an insurmountable problem if you're committed to using D, but when you are making a decision about what to use, it is a factor. For writing various server programs, if you want to work with a GC'ed, compiled to native code language, Go may be a much better choice than D right now. This is a problem with being such a wide spectrum language: D has to compete with high level GC'ed languages and will also need to compete with low level languages without GCs. That's a tough row to hoe!
Jul 05 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Friday, 4 July 2014 at 21:15:00 UTC, Chris Cain wrote:
 On Friday, 4 July 2014 at 21:09:05 UTC, Remo wrote:
 By "C++ style memory management" I do not mean naked 
 new/delete or malloc/free.
 What I mean is RAII, smart pointers and destructor's.
 What is the proper replacement for std::unique_ptr and 
 std::shared_ptr in D2 ?
 Of course with move support for unique_ptr :)

Ah, I see what you mean now. D has that: http://dlang.org/phobos/std_typecons.html#.Unique http://dlang.org/phobos/std_typecons.html#.RefCounted But they probably need some decent updating for use with nogc and more modern D style, though. Also the Unique pointer also works with std.algorithm.move (in addition to its "release" method which could be deprecated, I think... not sure why it needs it when we have std.algorithm.move).

This is what I have been referring to in my earlier comment. These utilities provide RAII experience very similar to one in C++ and work pretty good if you stick to certain style of programming. But they are implemented by using struct wrappers and all polymorphic traits are lost. C++ does not have this strong distinction between structs and classes resulting in a bit more flexible RAII application. Writing applications in C++ style is certainly possible but may require some rather advanced knowledge of what can and what can't be done. nogc helps here a lot.
Jul 05 2014
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
On Saturday, 5 July 2014 at 16:28:13 UTC, Dicebot wrote:
 This is what I have been referring to in my earlier comment. 
 These utilities provide RAII experience very similar to one in 
 C++ and work pretty good if you stick to certain style of 
 programming. But they are implemented by using struct wrappers 
 and all polymorphic traits are lost.

 C++ does not have this strong distinction between structs and 
 classes resulting in a bit more flexible RAII application. 
 Writing applications in C++ style is certainly possible but may 
 require some rather advanced knowledge of what can and what 
 can't be done.  nogc helps here a lot.

Hmm? And what classes you can cast std::unique_ptr to?
Jul 07 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Saturday, 5 July 2014 at 06:43:31 UTC, Russel Winder via
Digitalmars-d wrote:
 On Fri, 2014-07-04 at 20:25 +0000, Chris Cain via Digitalmars-d 
 wrote:
 […]
 The big problem with that is "C++ style memory management" 
 implies we're going to have new/delete which AFAIK delete is 
 depreciated and new is currently hardcoded to use the GC.

All the C++ folk are saying that with C++14 is you are using any heap at all you are more than likely doing it wrong. Modern C++ idiom is for completely new/delete free code.

With asynchronous event-driven code (ie. server code), I don't see any way to avoid all use of new / delete.
Jul 07 2014
prev sibling next sibling parent =?UTF-8?B?IsOBdGlsYQ==?= Neves" <atila.neves gmail.com> writes:
On Monday, 7 July 2014 at 18:15:32 UTC, Sean Kelly wrote:
 On Saturday, 5 July 2014 at 06:43:31 UTC, Russel Winder via
 Digitalmars-d wrote:
 On Fri, 2014-07-04 at 20:25 +0000, Chris Cain via 
 Digitalmars-d wrote:
 […]
 The big problem with that is "C++ style memory management" 
 implies we're going to have new/delete which AFAIK delete is 
 depreciated and new is currently hardcoded to use the GC.

All the C++ folk are saying that with C++14 is you are using any heap at all you are more than likely doing it wrong. Modern C++ idiom is for completely new/delete free code.

With asynchronous event-driven code (ie. server code), I don't see any way to avoid all use of new / delete.

std::make_unique and std::make_shared are what you're "supposed" to use. The new and delete operators are (usually) for library writers. Even before C++11, using delete was frowned upon but necessary with containers of pointers due to std::auto_ptr not helping. Well, that and the lack of move semantics. Atila
Jul 07 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 8 July 2014 at 02:31:50 UTC, Átila Neves wrote:
 On Monday, 7 July 2014 at 18:15:32 UTC, Sean Kelly wrote:
 With asynchronous event-driven code (ie. server code), I don't
 see any way to avoid all use of new / delete.

std::make_unique and std::make_shared are what you're "supposed" to use. The new and delete operators are (usually) for library writers. Even before C++11, using delete was frowned upon but necessary with containers of pointers due to std::auto_ptr not helping. Well, that and the lack of move semantics.

But you're ultimately passing something as a void* to a library call and receiving it later as the context for a callback. That value has to live on the heap.
Jul 08 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 8 July 2014 at 14:24:10 UTC, Sean Kelly wrote:
 But you're ultimately passing something as a void* to a library 
 call and receiving it later as the context for a callback.  
 That value has to live on the heap.

Well to be fair, you could make the context an index into an array.
Jul 08 2014
prev sibling next sibling parent "Atila Neves" <atila.neves gmail.com> writes:
On Tuesday, 8 July 2014 at 14:24:10 UTC, Sean Kelly wrote:
 On Tuesday, 8 July 2014 at 02:31:50 UTC, Átila Neves wrote:
 On Monday, 7 July 2014 at 18:15:32 UTC, Sean Kelly wrote:
 With asynchronous event-driven code (ie. server code), I don't
 see any way to avoid all use of new / delete.

std::make_unique and std::make_shared are what you're "supposed" to use. The new and delete operators are (usually) for library writers. Even before C++11, using delete was frowned upon but necessary with containers of pointers due to std::auto_ptr not helping. Well, that and the lack of move semantics.

But you're ultimately passing something as a void* to a library call and receiving it later as the context for a callback. That value has to live on the heap.

The point isn't that nothing lives on the heap in modern C++. It's that whatever does is wrapped in a class that manages the lifetime of the allocated memory for you. Atila
Jul 08 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 8 July 2014 at 15:23:30 UTC, Atila Neves wrote:
 On Tuesday, 8 July 2014 at 14:24:10 UTC, Sean Kelly wrote:
 On Tuesday, 8 July 2014 at 02:31:50 UTC, Átila Neves wrote:
 On Monday, 7 July 2014 at 18:15:32 UTC, Sean Kelly wrote:
 With asynchronous event-driven code (ie. server code), I 
 don't
 see any way to avoid all use of new / delete.

std::make_unique and std::make_shared are what you're "supposed" to use. The new and delete operators are (usually) for library writers. Even before C++11, using delete was frowned upon but necessary with containers of pointers due to std::auto_ptr not helping. Well, that and the lack of move semantics.

But you're ultimately passing something as a void* to a library call and receiving it later as the context for a callback. That value has to live on the heap.

The point isn't that nothing lives on the heap in modern C++. It's that whatever does is wrapped in a class that manages the lifetime of the allocated memory for you.

Well sure, but you can't use a class instance living on the stack as the context for a callback. At that point, whatever smart pointer you're using has to be discarded. This is actually why I find little use for std::shared_ptr--it has unique() and get() but no release() (which makes me wonder why they even bothered to offer unique()). It's kind of sad that the intended goal of not using raw pointers is actually forcing me to use raw pointers. In practice, I either use auto_ptr (now unique_ptr) for exception safety and release when passing to a function with a callback (in keeping with modern C++ idioms), or in containers and such I use my own shared_ptr that provides a release() function which fails if unique() is false.
Jul 08 2014
prev sibling next sibling parent "Brad Anderson" <eco gnuk.net> writes:
On Tuesday, 8 July 2014 at 17:55:15 UTC, Sean Kelly wrote:
 Well sure, but you can't use a class instance living on the 
 stack
 as the context for a callback.  At that point, whatever smart
 pointer you're using has to be discarded.  This is actually why 
 I
 find little use for std::shared_ptr--it has unique() and get()
 but no release() (which makes me wonder why they even bothered 
 to
 offer unique()).  It's kind of sad that the intended goal of not
 using raw pointers is actually forcing me to use raw pointers.
 In practice, I either use auto_ptr (now unique_ptr) for 
 exception
 safety and release when passing to a function with a callback 
 (in
 keeping with modern C++ idioms), or in containers and such I use
 my own shared_ptr that provides a release() function which fails
 if unique() is false.

Maybe I'm misunderstanding but why not just use reset()?
Jul 08 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 8 July 2014 at 18:04:14 UTC, Brad Anderson wrote:
 Maybe I'm misunderstanding but why not just use reset()?

reset deletes the currently referenced object.
Jul 08 2014
prev sibling parent "Brad Anderson" <eco gnuk.net> writes:
On Tuesday, 8 July 2014 at 18:23:41 UTC, Sean Kelly wrote:
 On Tuesday, 8 July 2014 at 18:04:14 UTC, Brad Anderson wrote:
 Maybe I'm misunderstanding but why not just use reset()?

reset deletes the currently referenced object.

Oh, I see what you were going for now.
Jul 08 2014