Macros

2001-05-04 Thread Jan-Willem Maessen

Alan Bawden <[EMAIL PROTECTED]> writes:
> A macro facility is like a pair of vise-grips (if you don't know what
> those are, see http://www.technogulf.com/ht-vise.htm).

I found myself laughing heartily at this apt analogy.  I have heard
vice grips described as "the wrong tool for every job."  (My own
experience with vice grips backs this up).

That being said, there are a number of things one might want out of a
macro facility, and I think they should be carefully distinguished:

1) The ability to name expressions without evaluating them, e.g. to
   cook up a facsimile of laziness.
2) The ability to parrot source code (and maybe source position) back
   at the user, e.g. Alan's assert macro, or its C equivalent.
3) The ability to create new binding constructs.
4) The ability to create new declaration constructs.

(1) is pretty well covered by lazy evaluation.  

For (2), I wonder if a clever set of compiler-supplied implicit
parameters might do the trick---after all, "the position of expression
e" and "the source code of expression e" are dynamic notions that
could be carefully defined.

(3) is trickier.  Contrast monadic code before and after "do" notation
was introduced.  Haskell made it possible---not even very hard---to do
monadic binding, but there was a good deal of ugly syntactic noise.
The introduction of "do" notation eliminated that noise.  My instinct
is that this isn't so easy for things that can't be shoehorned into a
monad.  For example, I use the Utrecht attribute grammar tool, and
have trouble imagining how grammars could be coded in pure Haskell
while preserving nice naming properties.

(4) is harder still.  Polytypic classes are a huge step in the right
direction.  What I most long for, though, is the ability to synthesize
new types and new classes---not just simple instance declarations.

As you can probably guess, I think (3) and (4) are the most profitable
avenues of exploration.  And I'm pretty sure I _don't_ want syntax
macros for these.  I'm still waiting to be convinced what I do want.

-Jan-Willem Maessen
Eager Haskell project
[EMAIL PROTECTED]


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Implict parameters and monomorphism

2001-05-04 Thread Marcin 'Qrczak' Kowalczyk

Fri, 4 May 2001 16:16:29 -0400, Dylan Thurston <[EMAIL PROTECTED]> pisze:

> I'm not sure I understand here.  One thing that occurred to me reading
> your e-mail was that maybe the implicit universal quantification over
> type variables is a bad idea, and maybe type variables should, by
> default, have pattern matching semantics.

Only for type signatures on patterns and results. It's a ghc/Hugs
extension. You can write:

f' arr :: ST s (a i e) = do
(marr :: STArray s i e) <- thaw arr
...

These type variables have the same scope as corresponding value
variables. The s,i,e in the type of marr refer to the corresponding
variables from the result of f'. You could bind i,e to new names in
marr, but not s. (Well, now I'm not sure why there is a difference...)

Type variables from the head of a class are also available in the
class scope in ghc.

You use bound type variables in ordinary type signatures on expressions
and let-bound variables in their scope. Unbound type variables in these
places are implicitly qualified by forall, I don't want to change this.

Some people think that type variables used in standard type signatures
(expressions and let-bound variables) should be available in the
appropriate scope. I don't have a strong opinion on that.

-- 
 __("<  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTÊPCZA
QRCZAK


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Macros

2001-05-04 Thread Alan Bawden

   Date: Thu, 3 May 2001 18:09:01 -0500 (EST)
   From: Dan Knapp <[EMAIL PROTECTED]>

   > >   (if (not (< x 3))
   > >   (assertion-failed '(< x 3)))
   > 
   > This is a good example, which cannot be implemented in
   > Haskell.  "Exception.assert" is built in to the ghc compiler, rather than
   > being defined within the language.  On the other hand, the built in
   > function gives you the source file and line number rather than the literal
   > expression; the macro can't do the former.

   Yeah, it's a good example, but are there any other uses for such quoting?

There are a few.  But this isn't the -only- reason to still use macros.

We could systematically go through all the macros I've written in the last
few years, and for each one we could figure out what language feature would
be needed in order to make that macro unnecessary.  At the end of the
process you would have a larger programming language, but I still wouldn't be
convinced that we had covered all the cases.

A macro facility is like a pair of vise-grips (if you don't know what those
are, see http://www.technogulf.com/ht-vise.htm).  You can do a lot of
things with a pair of vise-grips, although usually there's a better tool
for the job -- if you haven't got (say) a pipe-wrench, then a pair of
vise-grips can substitute.  Now the more tools you have in your tool box,
the less often you will use your vise-grips.  But no matter how bloated
your tool box becomes, you will still want to include a pair of vise-grips
for the unanticipated situation.

I have one problem with my own analogy: If you find yourself using your
vise-grips everyday for some task, you will probably soon go and purchase a
more appropriate tool.  But I think that in many circumstances macros do
such a good job that I don't see the need to clutter up the language with
the special-prupose features needed to replace them.

   Date: Fri, 04 May 2001 12:57:29 +0200
   From: Jerzy Karczmarczuk <[EMAIL PROTECTED]>

   ...
   I think that they are less than popular nowadays because they are dangerous,
   badly structured, difficult to write "hygienically"

Indeed, you can screw up pretty badly with a pair of vise-grips!  A friend
of mine used to say that programmers should have to pass some kind of
licensing test before they would be allowed to write Lisp/Scheme macros.

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Implict parameters and monomorphism

2001-05-04 Thread Dylan Thurston

On Fri, May 04, 2001 at 07:56:24PM +, Marcin 'Qrczak' Kowalczyk wrote:
> I would like to make pattern and result type signatures one-way
> matching, like in OCaml: a type variable just gives a name to the given
> part of the type, without constraining it any way - especially without
> "negative constraining", i.e. without yielding an error if it will
> be known more than that it's a possibly constrained type variable...

I'm not sure I understand here.  One thing that occurred to me reading
your e-mail was that maybe the implicit universal quantification over
type variables is a bad idea, and maybe type variables should, by
default, have pattern matching semantics.  Whether or not this is a
good idea abstractly, the way I imagine it, it would make almost all
existing Haskell code invalid, so it can't be what you're proposing.

Are you proposing that variables still be implicitly quantified in
top-level bindings, but that elsewhere they have pattern-matching
semantics?

Best,
Dylan Thurston

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Macros (Was: Interesting: "Lisp as a competitive advantage")

2001-05-04 Thread Marcin 'Qrczak' Kowalczyk

Fri, 04 May 2001 12:57:29 +0200, Jerzy Karczmarczuk <[EMAIL PROTECTED]> pisze:

> In Clean there are macros. They are rather infrequently used...

I think they roughly correspond to inline functions in Haskell.

They are separate in Clean because module interfaces are written
by hand, so the user can include something to be expanded inline in
other modules by making it a macro.

In Haskell module interfaces are generated by the compiler, so they
can contain unfoldings of functions worth inlining without explicit
distinguishing in the source.

-- 
 __("<  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTÊPCZA
QRCZAK


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Macros (Was: Interesting: "Lisp as a competitive advantage")

2001-05-04 Thread Keith Wansbrough

Jerzy Karczmarczuk <[EMAIL PROTECTED]> writes:

> Macros in Scheme are used to unfold n-ary control structures such as COND
> into a hierarchy of IFs, etc. Nothing (in principle) to do with laziness
> or HO functions.

Isn't this exactly the reason that macros are less necessary in lazy languages?

In Haskell you can write

  myIf True  x y = x
  myIf False x y = y

and then a function like

  recip x = myIf (abs x < eps) 0 (1 / x)

works as expected.  In Scheme,

(define myIf
  (lambda (b x y)
(if b x y)))

does *not* have the desired behaviour!  One can only write myIf using
macros, or by explicitly delaying the arguments.

--KW 8-)


___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Macros (Was: Interesting: "Lisp as a competitive advantage")

2001-05-04 Thread Jerzy Karczmarczuk


Discussion about macros, Lisp, laziness etc. Too many people to cite.
Alan Bawden uses macros to write assertions, and Dylan Thurston comments:

...
> >   (assert (< x 3))
> >
> > Which macro expands into:
> >
> >   (if (not (< x 3))
> >   (assertion-failed '(< x 3)))
> >
> > Where `assertion-failed' is a procedure that generates an appropriate error
> > message.  The problem being solved here is getting the asserted expression
> > into that error message.  I don't see how higher order functions or lazy
> > evaluation could be used to write an `assert' that behaves like this.
> 
> This is a good example, which cannot be implemented in
> Haskell.  "Exception.assert" is built in to the ghc compiler, rather than
> being defined within the language.  On the other hand, the built in
> function gives you the source file and line number rather than the literal
> expression; the macro can't do the former.
> 
> --Dylan Thurston


In general this is not true, look at the macro preprocessing in C. If your
parser is kind enough to yield to the user some pragmatic information about
the read text, say, __LINE etc., you can code that kind of control with
macros as well.

Macros in Scheme are used to unfold n-ary control structures such as COND
into a hierarchy of IFs, etc. Nothing (in principle) to do with laziness
or HO functions. They are used also to define object-oriented layers in
Scheme or Lisp. I used them to emulate curryfied functions in Scheme.

I think that they are less than popular nowadays because they are dangerous,
badly structured, difficult to write "hygienically". Somebody (Erik Meijer?)
asked: "Don't you get dynamic scoping as well with macros?" Well, what is
dynamic here? Surely this is far from "fluid" bindings, this is a good
way to produce name trapping and other diseases.

In Clean there are macros. They are rather infrequently used...

In C++ a whole zone of macro/preprocessor coding began to disappear with
the arrival of inlining, templates, etc.

I think that macros belong to *low-level* languages. Languages where you
feel under the parsing surface the underlying virtual machine. You can
do fabulous things with. My favourite example is the language BALM, many
years before ML, Haskell etc., there was a functional, Lisp-like language
with a more classical, Algol-like syntax, with infix operators, etc.

The language worked on CDC mainframes, under SCOPE/NOS. Its processor was
written in assembler (Compass). But you should have a look on it imple-
mentation! Yes, assembler, nothing more. But this assembler was so macro-
oriented, and so incredibly powerful, that the instructions looked like
Lisp. With recursivity, parentheses, LET forms which allocated registers,
and other completely deliciously crazy constructs. In fact, the authors
used macros to implement the entire Lisp machine, used to process BALM
programs. //Side remark: don't ask me where to find BALM. I tried, I failed.
If *YOU* find it, let me know//

Another place where macros have been used as main horses was the MAINBOL
implementation of Snobol4. But when people started to implement Spitbol
etc. variants of Snobol4, they decided to use more structured, higher-level
approach (there was even an another, portable assembler with higher-level
instructions "embedded"; these avoided the usage of macros).

Jerzy Karczmarczuk
Caen, France

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe



Re: Interesting: "Lisp as a competitive advantage"

2001-05-04 Thread Hannah Schroeter

Hello!

On Thu, May 03, 2001 at 06:09:01PM -0500, Dan Knapp wrote:
> [...]

>   Yeah, it's a good example, but are there any other uses for such quoting?
> If not, then implementing it as a builtin is perfectly adequate.  (Not
> trying to pick on Lisp; Lisp is great.  Just hoping for more examples.)

IMHO you can do all the things you'd do with separate preprocessing
steps for other languages with Lisp macros, inclusing scanner/parser
generating for some example. Or you could do the analogous thing
to camlp4 in Lisp with Lisp's own standard features (reader macros
+ normal macros).

You can e.g. also emulate Emacs Lisp in Common Lisp by slightly
hacking up the readtable and defining a few macros and functions
into a separate package. That's quite easy, in fact, the more complicated
part would be offering all those primitive functions of Emacs Lisp,
but if you had this, you could compile all those Emacs Lisp packages
into fast code. Imagine GNUs *not* crawling like a snail on a
Pentium 200 *g*

Kind regards,

Hannah.

___
Haskell-Cafe mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell-cafe