prog1

308 views
Skip to first unread message

Phlex

unread,
Nov 8, 2008, 5:55:14 AM11/8/08
to clo...@googlegroups.com
Hello,

I was missing the prog1 macro from common lisp, so here it is.

(defmacro prog1 [& body]
" (prog1 forms*)
Evaluates all the forms, returning the result of the first form"
`(let [result# ~(first body)]
~@(rest body)
result#))

user> (prog1 "a" "b" "c")
"a"
user> (prog1)
nil
user> (prog1 "a")
"a"

Might be usefull to have this in the language. Maybe it's already there
but couldn't find it !

Sacha

Stephen C. Gilardi

unread,
Nov 8, 2008, 9:22:18 AM11/8/08
to clo...@googlegroups.com

I came across a place where it would be useful as well, but worked
around it manually. "do1" would arguably fit better into Clojure's
naming scheme. I think none of "prog1", "prog2", or a hypothetical
"do1" have names that really jump out at a beginner with what they
mean (though of course, one isn't a beginner forever).

A collection of some useful CL macros written in Clojure would
probably make a nice addition to the wiki.

--Steve

Robert Pfeiffer

unread,
Nov 8, 2008, 11:10:54 AM11/8/08
to Clojure
Hello,

Is there a benefit in implementing this as a macro instead of a
function? The function version would be very simple:

(defn returning [returnval & body]
returnval)

This is just a K combinator with varargs.

Robert Pfeiffer

Meikel Brandmeyer

unread,
Nov 8, 2008, 11:39:19 AM11/8/08
to clo...@googlegroups.com
Hi,

Am 08.11.2008 um 17:10 schrieb Robert Pfeiffer:
> Is there a benefit in implementing this as a macro instead of a
> function? The function version would be very simple:
>
> (defn returning [returnval & body]
> returnval)

Although I'm a strong proponent of using macros only where they
are really needed, I would make an exception here. The function
might be simple and the use of a K combinator - whatever that is -
might be elegant, but it hides away the intent of the macro/function.
The macro expansion on the other hand is clear: evaluate the first
form, do the rest and return the first thing. The function call
hides away the "do the rest" step.

I apologise for being a peasant.

Sincerely
Meikel


Phlex

unread,
Nov 8, 2008, 11:47:36 AM11/8/08
to clo...@googlegroups.com

Robert Pfeiffer wrote:
> Hello,
>
> Is there a benefit in implementing this as a macro instead of a
> function? The function version would be very simple:
>
> (defn returning [returnval & body]
> returnval)
>
>
>

Well no, the forms are evaluated. It's usefull for side effects.

user> (def *bleh* (ref nil))
user> (prog1
(dosync (ref-set *bleh* 3))
(println (str "bleh is now " @*bleh*)))
bleh is now 3
3

A function would work :

(defn progz [return-value do-also-fn]
(do-also-fn)
return-value)

user> (progz (+ 1 3)
(fn []
(prn "hello")
(prn "i'm evaluated")))
"hello"
"i'm evaluated"
4

But it's not as terse.

Sacha

Randall R Schulz

unread,
Nov 8, 2008, 11:58:58 AM11/8/08
to clo...@googlegroups.com

Peasant? Or did you mean "pedant?"


> Sincerely
> Meikel


RRS

Meikel Brandmeyer

unread,
Nov 8, 2008, 12:00:25 PM11/8/08
to clo...@googlegroups.com
Hi,

Am 08.11.2008 um 17:39 schrieb Meikel Brandmeyer:
>> (defn returning [returnval & body]
>> returnval)

And another question, which a I got when I read the
mail of Phlex: Is the order of evaluation of function
arguments guaranteed to be from the left to the right?

Sincerely
Meikel

Meikel Brandmeyer

unread,
Nov 8, 2008, 12:32:59 PM11/8/08
to clo...@googlegroups.com
Hi,

Am 08.11.2008 um 17:58 schrieb Randall R Schulz:
> Peasant? Or did you mean "pedant?"

In german there is the word "Banause" which translates
according the dictionary to "peasant". It means something
like the following:

Artist: "Oh! Look this beautiful picture! It's art!"
Banause: "It's just a blob of blue color."

Sincerely
Meikel


André Thieme

unread,
Nov 8, 2008, 1:42:52 PM11/8/08
to Clojure
On 8 Nov., 17:47, Phlex <Ph...@telenet.be> wrote:
> Robert Pfeiffer wrote:
> > Hello,
>
> > Is there a benefit in implementing this as a macro instead of a
> > function? The function version would be very simple:
>
> > (defn returning [returnval & body]
> >    returnval)
>
> Well no, the forms are evaluated. It's usefull for side effects.

In what way would the forms *not* get evaluated when using
Roberts function returning?


> user> (def *bleh* (ref nil))
> user> (prog1
>         (dosync (ref-set *bleh* 3))
>         (println (str "bleh is now " @*bleh*)))
> bleh is now 3
> 3

user> (def *bleh* (ref nil))
#=(var user/*bleh*)
user> (returning
(dosync (ref-set *bleh* 3))
(println (str "bleh is now " @*bleh*)))
bleh is now 3
3


> A function would work :
>
> (defn progz [return-value do-also-fn]
>   (do-also-fn)
>   return-value)

Your function only takes two arguments.
Roberts took an arbitrary number of them.


> user> (progz (+ 1 3)
>         (fn []
>           (prn "hello")
>           (prn "i'm evaluated")))
> "hello"
> "i'm evaluated"
> 4
>
> But it's not as terse.

But this is:
user> (returning (+ 1 3)
(prn "Hello")
(prn "I'm evaluated"))
"Hello"
"I'm evaluated"
4


Macros are much less often needed in a functional language
which also comes with syntactic suger for (λ [args] ...) in form
of #(...).

André Thieme

unread,
Nov 8, 2008, 1:44:07 PM11/8/08
to Clojure
On 8 Nov., 18:32, Meikel Brandmeyer <m...@kotka.de> wrote:
> Hi,
>
> Am 08.11.2008 um 17:58 schrieb Randall R Schulz:
>
> > Peasant? Or did you mean "pedant?"
>
> In german there is the word "Banause" which translates
> according the dictionary to "peasant". It means something
> like the following:

The german word “Banause” is “Philistine” in english.
What you said is, that you are sorry for being a Bauer :-)

André Thieme

unread,
Nov 8, 2008, 1:48:42 PM11/8/08
to Clojure
I am very sure that Clojure guarantees this.
In a pure functional language (like Haskell) this has not
to be the case. As there are no side effects it absolutely
does not matter at all in what order anything is evaluated.
But Clojure is a functional and imperative language, and
for running Java we need this guarantee.

At a first glance I see no need for implementing that in
the core language, and also not as a macro.
This can easily be implemented as a function, as Robert
demonstrated.
I also don’t see how the function hides the “do the rest”
part. Maybe returning is not the best name, but how would
we benefit of a macro, which is more complicated and also
is not first class and can’t be passed around?

Randall R Schulz

unread,
Nov 8, 2008, 2:13:15 PM11/8/08
to clo...@googlegroups.com

I tried to keep this off the list, but I have recent ancestors whose
surname is Bauer, so tread carefully, please...


RRS

Phlex

unread,
Nov 8, 2008, 2:24:06 PM11/8/08
to clo...@googlegroups.com

André Thieme wrote:
> On 8 Nov., 17:47, Phlex <Ph...@telenet.be> wrote:
>
>> Robert Pfeiffer wrote:
>>
>>> Is there a benefit in implementing this as a macro instead of a
>>> function? The function version would be very simple:
>>>
>>> (defn returning [returnval & body]
>>> returnval)
>>>
>> Well no, the forms are evaluated. It's usefull for side effects.
>>
>
> In what way would the forms *not* get evaluated when using
> Roberts function returning?
>

Ah I guess you're right, either way it would be nice to have the
functionality available in clojure.
There must be some reason for CL to have it as a macro
(call-argument-limit perhaps ?)
Also there's not function call overhead with a macro. Though that should
not be a concern.


> Macros are much less often needed in a functional language
> which also comes with syntactic suger for (λ [args] ...) in form
> of #(...).
>

ahwell that's a debate... sure you can do much with lambdas. Some would
say that's a leaking abstraction.
I often implement some functionality as a higher order function, then
wrap it around in a macro.
Like a do-trie macro around a map-trie function. it's just prettier !

Sacha

Michael Wood

unread,
Nov 8, 2008, 2:28:44 PM11/8/08
to clo...@googlegroups.com
On Sat, Nov 8, 2008 at 8:48 PM, André Thieme
<splend...@googlemail.com> wrote:
>
> On 8 Nov., 18:00, Meikel Brandmeyer <m...@kotka.de> wrote:
>> Hi,
>>
>> Am 08.11.2008 um 17:39 schrieb Meikel Brandmeyer:
>>
>> >> (defn returning [returnval & body]
>> >> returnval)
[...]

> I also don't see how the function hides the "do the rest"
> part. [...]

I agree that it's not obvious, but that's only because body makes no
difference whatsoever, unless it causes side effects.

--
Michael Wood <esio...@gmail.com>

Matthias Benkard

unread,
Nov 8, 2008, 3:42:41 PM11/8/08
to Clojure
On 8 Nov., 20:24, Phlex <Ph...@telenet.be> wrote:
> There must be some reason for CL to have it as a macro
> (call-argument-limit perhaps ?)

I don't know, but I suspect it might be matter of aesthetics. In CL,
PROGN can't be a function for various reasons (off the top of my head:
multiple-value returns and special treatment at the top level), so
it'd be a bit weird and maybe even confusing for PROG1 or PROG2 to be
such.

Matthias

Christophe Grand

unread,
May 13, 2013, 11:25:44 AM5/13/13
to clojure
Hi


On Sat, Nov 8, 2008 at 5:10 PM, Robert Pfeiffer <pfeiffe...@googlemail.com> wrote:
Is there a benefit in implementing this as a macro instead of a
function? The function version would be very simple:

(defn returning [returnval & body]
   returnval)

The macro does not allocate a sequence of (count body) items.

Christophe 
Reply all
Reply to author
Forward
0 new messages