Statically typed, lisp-style cons lists in C++ :O

Started by
15 comments, last by CoffeeMug 18 years, 9 months ago
Quote:Original post by Andrew Russell
Quote:Original post by Shannon Barber
PS I'm pretty sure you can overload the comma operator.

You can *evil grin*.


And boost assignment library uses it [wink]. Did you know ->* (not * or ->) is overloadable [grin] i'm serious! its called member pointer operator
Advertisement
Quote:Original post by snk_kid
Quote:Original post by Andrew Russell
Quote:Original post by Shannon Barber
PS I'm pretty sure you can overload the comma operator.

You can *evil grin*.


And boost assignment library uses it [wink]. Did you know ->* (not * or ->) is overloadable [grin] i'm serious! its called member pointer operator


Not only did I know that, but I have indeed overloaded it. You see, I wanted to be able to use mem_fun_ptr with more than just raw pointers, so I created my own almost an exact clone (I think) of std::mem_fun_ptr that instead returned a structure who's operator() took a template parameter, rather than simply a raw pointer (although one could be provided as the template parameter) like so:
template < typename pointer_type >result_type operator()( pointer_type pointer ) const {	return (pointer->*function)();}

Of course, the pointer class in question must overload operator->*, which I found out was extremely nasty. Here's just for allowing ->* to work with zero and one argument functions, out of my cloning_ptr class:
//operator->* for pointer-to-member-0-argument-functiontemplate < typename result_type >boost::function< result_type ( void ) > operator->*( result_type (value_type::*function)( void ) ) {	return boost::bind( function , pointer );}template < typename result_type >boost::function< result_type ( void ) > operator->*( result_type (value_type::*function)( void ) const ) const {	return boost::bind( function , pointer );}		//operator->* for pointer-to-member-1-argument-functiontemplate < typename result_type , typename argument_type >boost::function< result_type ( argument_type ) > operator->*( result_type (value_type::*function)( argument_type ) ) {	return boost::bind( function , pointer );}template < typename result_type , typename argument_type >boost::function< result_type ( argument_type ) > operator->*( result_type (value_type::*function)( argument_type ) const ) const {	return boost::bind( function , pointer );}




Zahlman: I figured out how to get operator+= working with the left argument remaining a reference - you provide two functions:

template <typename car_t, typename cdar_t, typename cddr_t>const conslist< car_t , conslist<cdar_t, cddr_t> > operator+= (const car_t & x, const conslist<cdar_t, cddr_t>& y ) {  return conslist<car_t, conslist<cdar_t, cddr_t> >(x, y);}template < std::size_t size , typename car_t, typename cdar_t, typename cddr_t>const conslist< const car_t *, conslist<cdar_t, cddr_t> > operator+= (const car_t (&x)[ size ] , const conslist<cdar_t, cddr_t>& y) {  return conslist< const car_t *, conslist<cdar_t, cddr_t> >(x, y);}


Pretty? No, but it works. You may want to provide a third version with the constness removed:

template < std::size_t size , typename car_t, typename cdar_t, typename cddr_t>const conslist< car_t *, conslist<cdar_t, cddr_t> > operator+= (car_t (&x)[ size ] , const conslist<cdar_t, cddr_t>& y) {  return conslist< car_t *, conslist<cdar_t, cddr_t> >(x, y);}


Because otherwise the following will not work (this may or may not be intended):

void do_capitalize( char * c_string ) {    char * i = c_string;    while ( *i ) {        *i = toupper( *i );        ++i;    }}template < typename T >void capitalize( const T & l ) {    do_capitalize( l.car() );    capitalize( l.cdr() );}template <>void capitalize( const nil & n ) {}char foo[] = "...";char bar_array[] = "...";char bar * = bar_array;capitalize( foo += nil() ); //error without non-const version, foo treated like (const char *)capitalize( bar += nil() ); //ok, bar treated like (char *)
Quote:Original post by MaulingMonkey
Because otherwise the following will not work (this may or may not be intended):


That was intended; the expectation would be that one would return a new list with the capitalized values: return do_capitalize(l.car()) += capitalize(l.cdr()) (and the nil version returning nil() of course). For better lisp flavour. OTOH, it's probably better C++ flavour not to restrict yourself so arbitrarily :)
Neat stuff. And you're not just using Lisp... why? :P
-----http://alopex.liLet's Program: http://youtube.com/user/icefox192
I don't particularly like Lisp; I find that the purer, early versions are just a poor fit for my thinking, and more elaborate systems are just plain weird. Plus, it's hard to think recursively *all* the time. ;)

Really, I'm just doing it for fun. Although, the static typing here results in significant gains in space efficiency (at the cost of potentially quite a bit of extra generated code) - dynamic typing systems typically get implemented with a lot of pointer trickery.
All this talking about lisp in C++ reminds me of my attempt at smalltalk in C++.

Quote:Originally posted by MaulingMonkey:
int main ( int argc , char ** argv ) {	try {		application_config config;		vector< string > args( argv + 1 , argv + argc );		parse( args ).into( config.wall ); //this line	} catch( const exception & e ) {		report_exception( e );		return 0;	}}
This is pretty cool. Now onto implementing eval:
eval("int i = 0;");i = 5;cout << i;-----Output:5

This topic is closed to new replies.

Advertisement