The Artima Developer Community
Sponsored Link

Weblogs Forum
Macros and Type-Systems

35 replies on 3 pages. Most recent reply: Oct 11, 2005 4:19 AM by Steve Donovan

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 35 replies on 3 pages [ 1 2 3 | » ]
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Macros and Type-Systems (View in Weblogs)
Posted: Oct 2, 2005 2:16 PM
Reply to this message Reply
Summary
Macros are a frequently overlooked yet tremendously useful language feature. What if we give them a more modern twist?
Advertisement
Any selection of imperative language constructs a language designer comes up with is completely arbitrary, and is going to be limiting in one way or another. I think the best way to deal with this problem is to provide macros. When I talk about macros I am not talking about the nasty C pre-processor, but something more closely resembling macros in MacroML or Lisp.

I envision macros being well-integrated into the language and part of the type system. For instance it makes sense to me to be able to pass macros as template parameters. It also makes sense for macro parameters to be typed.

Consider the following code:

int x;
repeat (42) { ++x; }
This is not valid Heron code, but it makes sense. Instead of adding a new language construct my plan is to allow the programmer to define it as a macro as follows:
macro repeat('int A, 'code B)
  _cond(A <= 0, {}, true, ($B, repeat(A - 1, B)));
So as you may realize the macro is defined using a functional meta-language. _cond is the same as the Lisp function COND. The 'int represents a meta-int value, which is equivalent to a constant literal integer value. The 'code represents a statement or code block. The above example clearly won't work in the following scenario:
int x;
repeat (read_int()) { ++x; }
However, a new overloaded repeat macro can be defined as follows:
macro repeat(int A, 'code B)
  ${
    int _i = A;
    while (_i > 0) {
      $B
      --_i;
    }
  }
Any thoughts or suggestions? Think it is time for better macros and code-rewriting tools in modern languages?


Kristian Dupont

Posts: 22
Nickname: chryler
Registered: Dec, 2003

Re: Macros and Type-Systems Posted: Oct 3, 2005 2:26 AM
Reply to this message Reply
Why not go the whole length and just turn it into a genuine multi-stage language?

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Macros and Type-Systems Posted: Oct 3, 2005 8:50 AM
Reply to this message Reply
> Why not go the whole length and just turn it into a
> genuine multi-stage language?

I am open to the idea, but what specifically is lacking to make it a "genuine" multi-stage language? What would be the advantages and disadvantages?

Kristian Dupont

Posts: 22
Nickname: chryler
Registered: Dec, 2003

Re: Macros and Type-Systems Posted: Oct 3, 2005 10:33 AM
Reply to this message Reply
Take a look at Meta OCaml or `C (Tick C - which has only two levels though). The advantages would be that you have an entire programming language for the meta programming rather than some exotic spinoff using a different paradigm (the meta programming that you can do with C++ and, I reckon, Heron, resembles a functional language much more than the host language).
You would need some sort of staging construct. I guess TickC would be your best source of inspiration here - it allows you to write code literals, I think, using a back quote operator. I haven't used it though so I am not quite sure.

Tanton Gibbs

Posts: 20
Nickname: tanton
Registered: Aug, 2005

Re: Macros and Type-Systems Posted: Oct 3, 2005 3:13 PM
Reply to this message Reply
I think Template Haskell would also be an interesting language to look at. Metaprogramming is going to be so important in the future that this would be a great addition to Heron!

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Macros and Type-Systems Posted: Oct 3, 2005 7:43 PM
Reply to this message Reply
> Take a look at Meta OCaml or `C (Tick C - which has only
> two levels though).

Thanks for the suggestions.

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Macros and Type-Systems Posted: Oct 3, 2005 7:44 PM
Reply to this message Reply
> I think Template Haskell would also be an interesting
> language to look at.

I will check it out.

> Metaprogramming is going to be so
> important in the future that this would be a great
> addition to Heron!

Thanks for the encouragement.

Terje Slettebø

Posts: 205
Nickname: tslettebo
Registered: Jun, 2004

Re: Macros and Type-Systems Posted: Oct 4, 2005 5:50 AM
Reply to this message Reply
Even if you don't go all the way to a multi-stage language, or something like that, what you've shown in the examples is typically called unnamed functions or lambda functions, which I'm sure you're aware of.

These exist in various forms in some other languages as, well, such as in Smalltalk, where you can pass a code block to a method. It can also be done, to some extent (and with a "ton" of library code) in C++ with Boost.Lambda.

A challenge with lambda functions is references to variables outside the function, and managing their lifetimes (such as if you store a lambda function for later use, such as a callback). Java "simulates" somewhat such lambda functions/closures with anonymous inner functions, where the compiler inserts references to external variables, where needed, in the generated code, and lifetimes being handled with the garbage collector (actually, it only handles storage, since GC in effect simulates "infinite lifetime").

It would have been nice with support for lambda in C++, as well, but with all the proposals being worked at (such as support for concepts, and DbC), it probably won't be included in the next standard.

Regards,

Terje

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Macros and Type-Systems Posted: Oct 4, 2005 9:56 AM
Reply to this message Reply
> Even if you don't go all the way to a multi-stage
> language, or something like that, what you've shown in the
> examples is typically called unnamed functions or lambda
> functions, which I'm sure you're aware of.

The proposed Heron macro is similar but does not have a stack frame and, at least for now, can't be recursive. The macro is always inlined.

> These exist in various forms in some other languages as,
> well, such as in Smalltalk, where you can pass a code
> block to a method. It can also be done, to some extent
> (and with a "ton" of library code) in C++ with
> Boost.Lambda.
>
> A challenge with lambda functions is references to
> variables outside the function, and managing their
> lifetimes (such as if you store a lambda function for
> later use, such as a callback).

One solution to this problem I have been exploring is that closures (my definitions: functions referring to variables outside of the scope of the function) as having a lifetime which is equivalent to the shortest lived object referenced.

So:

{
  int x;
  {
    def f() {
      return x;
    }
    f(); // fine
  }  
  f(); // fine
}
f(); // runtime-error

I mention this approach in the thread "Musing about Closures" http://www.artima.com/forums/flat.jsp?forum=106&thread=129705 . This seems to be a novel idea, but I am still trying to ascertain the expressive power of it. It is not as powerful as a closure in many functional languages, but IMO it is still very useful.

> Java "simulates" somewhat
> such lambda functions/closures with anonymous inner
> functions, where the compiler inserts references to
> external variables, where needed, in the generated code,
> and lifetimes being handled with the garbage collector
> (actually, it only handles storage, since GC in effect
> simulates "infinite lifetime").

The "infinite lifetime" of objects in a GC, is exactly something I want to avoid in Heron at all costs. The idea of a programmer unintentionally extending lifetimes of objects, and having to do extensive post-analysis to identify object lifetime issues, is a nightmare I want to avoid.

Rinie Kervel

Posts: 26
Nickname: rinie
Registered: Oct, 2005

Re: Macros and Type-Systems Posted: Oct 4, 2005 11:30 AM
Reply to this message Reply
> {
> int x;
> {
> def f() {
> return x;
> }
> f(); // fine
> }
> f(); // fine
> }
> f(); // runtime-error

Doesn't this spell 'side effects' / globals considered harmfull.
I was taught Pascal with blockscope / nested functions and later switched to C/C++ being only 2 level (or 3 including class level)

So what is the benefit of closures? Is the model of only local variables, parameters and / or class members not much clearer with regards to sideeffects?

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Macros and Type-Systems Posted: Oct 4, 2005 11:41 AM
Reply to this message Reply
> Doesn't this spell 'side effects' / globals considered
> harmfull.

Why do you say that, and what specifically do you mean by it?

> I was taught Pascal with blockscope / nested functions and
> later switched to C/C++ being only 2 level (or 3 including
> class level)
>
> So what is the benefit of closures?

Things like:

def output_all(list a)
{
  int x; 
  def out(object o) { 
    write(x++); 
    write(" : ");
    write(o); 
    write('\n');
  }
  a.witheach(out);
}


> Is the model of only
> local variables, parameters and / or class members not
> much clearer with regards to sideeffects?

I don't believe it to be so.

Max Lybbert

Posts: 314
Nickname: mlybbert
Registered: Apr, 2005

Re: Macros and Type-Systems Posted: Oct 4, 2005 4:25 PM
Reply to this message Reply
/* So what is the benefit of closures? Is the model of only local variables, parameters and / or class members not much clearer with regards to sideeffects?
*/

My understanding of closures is that we're talking about local variables. A closure is simply a technique that that lets you pass variables to a function/function like object a few at a time, and then get the return value after you've passed all the necessary parameters.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Macros and Type-Systems Posted: Oct 4, 2005 4:42 PM
Reply to this message Reply
> A closure is simply a technique that that lets you pass
> variables to a function/function like object a few at a
> time, and then get the return value after you've passed all
> the necessary parameters.

What you describe above sounds very much like one particular implementation technique called lambda lifting: http://www.google.com/search?q=lambda+lifting . There are other ways to implement first-class anonymous functions with lexical scoping.

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Re: Macros and Type-Systems Posted: Oct 4, 2005 5:42 PM
Reply to this message Reply
> This seems to be a novel idea, but I am still trying to
> ascertain the expressive power of it.

I'm a bit too lazy at the moment to dig my bookshelf for references, but I think that Pascal already incorporated a very similar idea. The idea is that a procedure may contain nested procedures that may refer to the local variables of the surrounding procedure. This was called block structure: http://www.google.com/search?q=block+structure+pascal . Actually, I think that there are several languages that effectively incorporate the same idea. In Lisp parlance it was called downward funargs: http://www.google.com/search?q=downward+funargs .

Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

Lexical scoping Posted: Oct 4, 2005 5:51 PM
Reply to this message Reply

{
int x;
{
def f() {
return x;
}
f(); // fine
}
f(); // fine
}
f(); // runtime-error


Assuming that curly braces are used to denote blocks/scopes, then the above seems rather meaningless to me. The last two f(); calls should be compile-time errors (unless, of course, an outer scope contains another definition of f).

Flat View: This topic has 35 replies on 3 pages [ 1  2  3 | » ]
Topic: Announcing Ruby Code & Style Previous Topic   Next Topic Topic: Threading Terminology


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us