Re: SBCL is now faster than Java, as fast as Ocaml, and getting better



Marco Antoniotti wrote:
On Jul 13, 2:42 am, Jon Harrop <j...@xxxxxxxxxxxxxxxxx> wrote:
Perhaps we can get to the root of your misconception: what exactly do you
mean by "just isn't the same" given that they have the same capabilities?

camlp4 is a pre-processor and its "language" is not Ocaml; similar
yes, but no cigar.

I give a trivial counter example below.

You invoke it on the command line (e.g., with the - pp option to ocamlc).

You can also load and use Camlp4 interactively, as I do below.

Plus it seems to rely on deep knowledge of the Ocaml internal AST
implementation.

Yet the OCaml macro you cited made no reference to or use of the OCaml AST.

I am not saying that you cannot
use camlp4 to do very fancy things. After all it is (it *has* to be!)
a full blown parser. camlp4 is a good thing and quite a feat; plus, I
do think that some of the best language and compiler people nowadays
are working on Ocaml and friends. Yet, it just is not the same as
DEFMACRO.

Indeed, Camlp4 supports a rich syntax including precedence and associativity
levels in a typeful way whereas DEFMACRO does not.

camlp4 is more like using SQL embedded in C/C++, while in
CLSQL you do

(select [emplid] [last-name] :from [employee] :where [= [emplid]
42])

Full blown CL!

You can do the same in OCaml, of course.

To continue, I have not seen a similar facility in F# (I mean camlp4-
like: again, I may be wrong).

There is no such facility in F#.

Let's look at the following code snippets.

Snippet 1:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defgeneric iter (f container)
(:method ((f symbol) (c t)) (iter (symbol-function f) c))
(:method ((f function) (c list)) (map nil f c))
(:method ((f function) (c vector)) (map nil f c))
(:method ((f function) (c hash-table)) (maphash f c))
)
;;; 6 lines for ITER.

(defmacro foreach ((vs in-kwd container) &body forms)
(assert (string-equal 'in in-kwd))
`(iter (lambda ,(if (symbolp vs) (list vs) vs) ,@forms) ,container))
;;; 3 lines for FOREACH. You can make it 2: witness DOLIST.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

... just to be a little more sophisticated, let's make things a little
more interesting (and rightly so, for the sake of the argument).
Let's substitute FOREACH with FOR-EACH.

Snippet 2:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defmacro for-each (&whole for-form vs in-kwd container &body forms)
(let ((lvar (if (symbolp vs) vs (gensym))))
(cond ((string-equal 'in in-kwd) ; one at a time...
`(iter (lambda (,lvar)
,@(if (symbolp vs) forms `((destructuring-
bind ,vs ,lvar ,@forms))))
,container))
((and (string-equal 'over in-kwd) (null (assert (listp
vs))))
`(iter (lambda ,vs ,@forms) ,container))
(t (error "Invalid FOR-EACH syntax ~S." for-form)))))
;;; 9 lines for FOR-EACH.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

The second version just separates the multiple lambda arg from the
destructuring version. If we had "patterns", things would have to
look different. You can use it as

(for-each x in '(1 2 3) (print x)
(for-each (x y z) in '((1 2 3) (4 5 6)) (print (list z y x)))
(for-each (k v) over some-hash-table (format t "~S -> ~S~%" k v))

The above was a half an hour hack. (I counted by thinking 10 minutes,
doubled it and added 10 extra minutes for precision). Don't take it
too seriously. Yet it "works".

After apples, let's now look at oranges.

http://www.ocaml-tutorial.org/camlp4_3.10/foreach_tutorial

Very nice, but I direct the reader at the full blown "for" example at
the end, which, admittedly, leverages OCaml to do somewhat more that
the CL code above.

Indeed, the OCaml supports precedence, associativity and pattern matching
whereas the Lisp does not.

It definitively may have the look'n'feel of MLish languages, but it is
different from OCaml.

In other words, it is a language extension.

And it requires an off-line call at the command line.

Not true.

Finally it is 17 lines long (actually 36 if you count all the
necessary supporting code). Now, which language is more verbose?

Now consider my working vanilla OCaml implementation and example:

# #load "camlp4oof.cma";;
Camlp4 Parsing version 3.10.2

# open Camlp4.PreCast;;
# open Syntax;;
# EXTEND Gram
expr: LEVEL "top"
[ [ "foreach"; p = ipatt; "in"; m = a_UIDENT; seq = expr; "do";
body = do_sequence ->
<:expr< $uid:m$.iter (fun $p$ -> $body$) $seq$ >> ] ];
END;;
- : unit = ()
# foreach x, y in List [1, 2; 3, 4] do
Printf.printf "%d, %d\n" x y
done;;
1, 2
3, 4
- : unit = ()

Note the following points:

.. No command-line arguments were used.

.. This macro is written entirely in OCaml.

.. Everything is done entirely from the interactive session.

.. This OCaml macro requires only 6 lines of code to achieve the same effect,
compared to 11 lines of your FOR-EACH Lisp macro.

.. This OCaml macro supports full pattern matching.

The above code took 60 seconds to write and test.

Please stop trying to tell me that camlp4 is "off-line", requires
command-line arguments, is not OCaml and requires deep AST knowledge.

--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com/products/?u
.



Relevant Pages

  • Re: camlp4r sequence
    ... Following descriptions in the camlp4 manuals, ... How do you parse and capture a sequence of expressions between ... Post to the OCaml mailing list and say which version of camlp4 you're using ... (i.e. pre or post OCaml 3.10). ...
    (comp.lang.functional)
  • Re: Very poor Lisp performance
    ... > OCaml has camlp4. ... O yeh, and C has yacc. ... Ivan Boldyrev ...
    (comp.lang.lisp)