Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

【R5RS scheme】C-lang like loop macros

132 views
Skip to first unread message

Hidekazu IWAKI

unread,
Sep 27, 2012, 9:53:02 AM9/27/12
to
Hi! I made C-lang like macros, "for" and "while" with break statement.
They are not unloved in popular functional programming culture. But if your friends take an interested in functional programming languages, you will be able to recommend this macros as an introduction.

;; `for` macro
(define-syntax for
(syntax-rules (= :)
((_ (var = init : cnd @ step) body)
(call-with-current-continuation
(lambda (@)
(letrec ((doloop (lambda (DUMMY var)
(if cnd
var
(doloop body step)))))
(doloop #f init)))))
((_ (var = init : cnd @ step) body ...)
(for (var = init : cnd @ step) (begin body ...)))
))
;; `while` macro
(define-syntax while
(syntax-rules ()
((_ cnd @ body)
(call-with-current-continuation
(lambda (@)
(letrec ((doloop (lambda (DUMMY)
(if (not cnd)
#t
(doloop body)))))
(doloop #f)))))
((_ cnd @ body ...)
(while cnd @ (begin body ...)))
))
;; Usage `for`
> (for (x = 0 : (= x 10) @ (+ x 1))
(display x)
(newline)
(if (= x 4) (@ x)) ;; `@` means the break command.
)
0
1
2
3
4
4
;; Usage `while`
(define idx 0)
> (while #t @
(display idx)
(newline)
(set! idx (+ idx 1))
(if (= idx 10) (@ idx)))
0
1
2
3
4
5
6
7
8
9
10

Pascal J. Bourguignon

unread,
Sep 27, 2012, 9:58:42 AM9/27/12
to
Hidekazu IWAKI <i.hid...@gmail.com> writes:

> Hi! I made C-lang like macros, "for" and "while" with break statement.
> They are not unloved in popular functional programming culture. But if
> your friends take an interested in functional programming languages,
> you will be able to recommend this macros as an introduction.
>
> ;; `for` macro
> (define-syntax for

Totally useless here. Try comp.lang.scheme instead!

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

Kaz Kylheku

unread,
Sep 27, 2012, 11:34:14 AM9/27/12
to
On 2012-09-27, Hidekazu IWAKI <i.hid...@gmail.com> wrote:
> Hi! I made C-lang like macros, "for" and "while" with break statement.

Hi, we already have a standard loop macro in Lisp which does all
that and more.

(loop for x = 0 then (1+ x)
while (< x 10) do
(print x)
if (= x 5) do
(return 42))

Output:
0
1
2
3
4
5

Result:
42


> They are not unloved in popular functional programming culture. But if your

For loops are absolutely reviled in functional programming culture.

> friends take an interested in functional programming languages, you will be
> able to recommend this macros as an introduction.

Unfortunately, this is wrongheaded because iteration with loops and increment
variables has no place in functional functional programming: it is imperative
programming.

Hidekazu IWAKI

unread,
Sep 28, 2012, 9:33:22 PM9/28/12
to
OK. you're right

But my plan is how to write programs in functional languages for imperative programmers.
I want to make a beginner course for non-functional programmers.

In addition, if my macros expand, then they look non-imperative. They are essentially functional.

2012年9月28日金曜日 0時34分18秒 UTC+9 Kaz Kylheku:

Pascal J. Bourguignon

unread,
Sep 28, 2012, 9:53:36 PM9/28/12
to
Hidekazu IWAKI <i.hid...@gmail.com> writes:

> OK. you're right
>
> But my plan is how to write programs in functional languages for
> imperative programmers.
>
> I want to make a beginner course for non-functional programmers.

Well, unless you're targetting BASIC programmers, you can as well write
programs in functional programming style in the languages known to
imperative programmers.

------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

typedef struct pair { int car; struct pair* cdr; } pair;

pair* cons(int a,pair* d){
pair* c=malloc(sizeof(pair));
if(c){ c->car=a; c->cdr=d; }
return(c);}

pair* cdr(pair* c){ return(c?c->cdr:c); }
int car(pair* c){ return(c?c->car:0); }

typedef int (*ifun)(int,int);

int reduce(ifun fun,pair* list,int initial){
return(list
? reduce(fun,cdr(list),fun(car(list),initial))
: initial);}

int plus(int a,int b){ return(a+b); }

int main(){
printf("%d\n",reduce(plus,cons(1,cons(2,cons(3,NULL))),0));
return(0);
}
------------------------------------------------------------------------

Just compile if with -lgc if you're afraid of using too much memory.

Kaz Kylheku

unread,
Sep 29, 2012, 12:00:56 AM9/29/12
to
On 2012-09-29, Hidekazu IWAKI <i.hid...@gmail.com> wrote:
> OK. you're right
>
> But my plan is how to write programs in functional languages for imperative
> programmers. I want to make a beginner course for non-functional
> programmers.

I appreciate that you're trying to connect something unfamiliar with
something familiar (which is how we generally teach things), but I'm afraid
that in this manner you will create a course in which you simply make yourself
look frightfully (and impractically) intelligent to some programmers who have
no clue what you're doing. :)

> In addition, if my macros expand, then they look non-imperative. They are essentially functional.

Yes; I see you are using continuations and letrec and such so that a loop
variable like 'x' is not a simple imperative variable, but is actually newly
instantiated in each iteration (so that, for example, we can capture
each different x in a different closure).

I really don't think this is a good way to introduce functional programming
to "non-functional" programmers.

You already have to understand it for it to be even interesting. And it is
quite complicated. You have hygienic macros, continuations, letrec. It is very
advanced for a beginner course (even as "further studies" material in
the last lecture).

The subtle difference between an imperative loop and the functional simulation
of a loop will likely not be properly understood (not to mention the rationale
for *why* that kind of thing is a good idea).

Imperative programmers will probably not be impressed that you can achieve a
for loop with functional programming and macros, and may get the impression
that something simple and familiar is a struggle to achieve in functional
programming, and after all the effort, is still bogged down with limitations.
(Like that you cannot assign to the dummy variable x in order to influence the
loop iteration.)

It also doesn't really represent how functional programming is typically done
or what makes it useful in the real world!

Imperative programmers learning functional programming do not really need the
comfort of knowing that they can continue to write Fortran-like code, if they
just pile some Scheme macros over continuations. Do not condescend to those
poor people in this way! :)

Nils M Holm

unread,
Sep 29, 2012, 1:51:56 AM9/29/12
to
Hidekazu IWAKI <i.hid...@gmail.com> wrote:
> But my plan is how to write programs in functional languages for
> imperative programmers.
> I want to make a beginner course for non-functional programmers.
>
> In addition, if my macros expand, then they look non-imperative.
> They are essentially functional.

Why not just use named LET and CALL/CC then?

(call/cc
(lambda (exit)
(let loop ((i 1))
(if (= i 10)
(exit 'foo))
(display i)
(newline)
(loop (+ 1 i)))))

Of course, it looks nicer with LET/CC instead if CALL/CC:

(define-syntax let/cc
(syntax-rules ()
((_ cc expr)
(call/cc (lambda (cc) expr)))))

If you really want to introduce your own looping constructs,
I would at least use some plain syntax without any fancy
characters in the forms. E.g.:

(for (i 1) (<= i 10) expr ...)

Random characters in forms make code walking unnecessarily
hard, so why present this approach to beginners?

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Hidekazu IWAKI

unread,
Sep 29, 2012, 11:32:12 AM9/29/12
to
Hi.
My understanding of your opinions are
1. It isn't a good way to teach functional programming since the macros are quite complete and advanced techniques.
2. The macros will not lead imperative programmer to typical functional programming. They will misunderstand about functional programming.

Of course, now that you say that, but if I follow such a line, I can't explain anything. I'm not a special instructor of lisp for beginner.

I want only to recommend scheme to my friends casually.
Please imagine if a person talk about the first experience language for his friends in very detail, the man will lose them later.
I don't want to lose my friends.

uh.. So, I'll use this macros as a non-typical functional code.

2012年9月29日土曜日 13時00分59秒 UTC+9 Kaz Kylheku:

Nils M Holm

unread,
Sep 29, 2012, 12:24:37 PM9/29/12
to
Hidekazu IWAKI <i.hid...@gmail.com> wrote:
> uh.. So, I'll use this macros as a non-typical functional code.

There are lots of constructs that may look familiar to users of
imperative languages and map to the functional paradigm quite
nicely, e.g. named LET, DO, and recursive procedures. If you
show these concepts to your friends first, you can later demonstrate
how they map to equivalent forms that are purely functional.

E.g.:

(define (rev x)
(do ((x x (cdr x))
(r '() (cons (car x) r)))
((null? x) r)))

Later show them named LET or LETREC

(define (rev x)
(letrec
((rev2 (lambda (x r)
(if (null? x)
r
(rev2 (cdr x) (cons (car x) r))))))
(rev2 x '())))

And then demonstrate how one maps to the other (this will
require a Scheme environment that can expand macros without
evaluating them):

(macro-expand-1
'(do ((x x (cdr x))
(r '() (cons (car x) r)))
((null? x) r)))
==>
(letrec
((g860
(lambda (x r)
(if (null? x)
(begin r)
(begin (g860 (cdr x) (cons (car x) r)))))))
(g860 x '()))

This approach would not even require you to invent new syntax.
Scheme already has some syntactic sugar that looks pretty
imperative.

Pascal J. Bourguignon

unread,
Sep 30, 2012, 1:33:47 AM9/30/12
to
Hidekazu IWAKI <i.hid...@gmail.com> writes:

> Hi.
> My understanding of your opinions are
> 1. It isn't a good way to teach functional programming since the
> macros are quite complete and advanced techniques.
> 2. The macros will not lead imperative programmer to typical
> functional programming. They will misunderstand about functional
> programming.
>
> Of course, now that you say that, but if I follow such a line, I can't
> explain anything. I'm not a special instructor of lisp for beginner.
>
> I want only to recommend scheme to my friends casually.

If they're friends, perhaps they trust your judgement, then you can just
tell them to learn scheme without giving anymore details. Point them to
scheme resources on the web: http://schemers.org/
http://xivilization.net/~marek/tex/schemerocks/schemerocks.pdf
etc.


> Please imagine if a person talk about the first experience language
> for his friends in very detail, the man will lose them later. I don't
> want to lose my friends.

If they're already programmers, they should withstand detailled
explainations about a programming language. Otherwise, you may still be
friend with them, but distrust their programming abilities.


> uh.. So, I'll use this macros as a non-typical functional code.

Macros are not sued for functional style programming. They're used for
metalinguistic style programming (integrated DSL).

Read again my C example. Functional style programming is characterized
by the use of functions as first class objects, and higher order
functions, and the possibility to make recursive function calls. The
important part of my example, is how you can pass a function such as
plus as argument to a function reduce, and how plus and reduce don't
need to use assignation (beside initialization), but just return a new
result given as an expression of function calls.

Of course, one difficulty doing this in C, is that when you have a chain
of function calls such as:

int s=reduce(plus,cons(1,cons(2,cons(3,NULL))),0);

the memory allocated by cons(1,cons(2,cons(3,NULL))) is not freed
automatically. You have to use a garbage collector. For this you can
use BoehmGC (-lgc) or implement one inside your program, but since
there's BoehmGC, it's not even worth speaking of it.

So the advantage of lisp, is that it was the language for which garbage
collection was invented, in 1959. That's why historically functional
programming style has been taught with LISP; FORTRAN and COBOL lacked
recursive function calls, functions as first class object and garbage
collection; C and Pascal lacked garbage collection, but you could still
teach functional programming style with C or Pascal, since you have
first class functions (well half class functions in Pascal) and
recursive function calls in C or Pascal.

One thing that has been added to the functional programming style since,
was closures. (C didn't have closures or anonymous functions until 2011,
Pascal had only delimited closures: local functions can access visible
global and local variable when they're called from a function called in
the same dynamic scope, but they cannot be returned or stored, so they
cannot be called from a different dynamic scope).

(Anonymous functions are only a syntactic nicety, they're not
fundamental to functional programming style, but they're quite practical
indeed. You could still write program in a language that wouldn't allow
literal numbers or literal strings.)


So my definition of the functional programming style is:
- functions are first class objects.
- you can make recursive calls.
- you can make closures.
- there's a garbage collector, or a way to deal with the memory
allocated for function results.

Of course, wikipedia differs, but I'm just a lisper ;-) :
http://en.wikipedia.org/wiki/Functional_programming

Hidekazu IWAKI

unread,
Sep 30, 2012, 8:26:03 AM9/30/12
to
Your explanation is really clear.
I can't add some description of functional programming.

I also try to explain to my friends such a explanation.
But it looks like they try to program in functional, only once.
So, to tell the truth, I'll not give lesson so much seriously.
Honestly, I wanted some good example codes or macros in R5RS scheme
for the lesson at first.

Thank you for your encouragements!

2012年9月30日日曜日 14時33分49秒 UTC+9 informatimago:
0 new messages