unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Dotted pair call argument
@ 2012-02-21 14:03 David Kastrup
  2012-02-21 15:36 ` Mark H Weaver
  0 siblings, 1 reply; 9+ messages in thread
From: David Kastrup @ 2012-02-21 14:03 UTC (permalink / raw)
  To: guile-devel


Hi, I am not sure whether this is a Scheme feature, but it seems
inconvenient that

((lambda (a . b) b) 1 . 2)

bombs out.  The same with

(apply (lambda (a . b) b) 1 2)

I guess my "real" problem is that I'd like to do call wrapping by writing

(lambda ( . x) (fun . x))

instead of having to write

(lambda ( . x) (apply fun x))

I assume eval is not supposed to try dealing with dotted lists?

-- 
David Kastrup




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 14:03 Dotted pair call argument David Kastrup
@ 2012-02-21 15:36 ` Mark H Weaver
  2012-02-21 15:59   ` David Kastrup
  0 siblings, 1 reply; 9+ messages in thread
From: Mark H Weaver @ 2012-02-21 15:36 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:
> I guess my "real" problem is that I'd like to do call wrapping by writing
>
> (lambda ( . x) (fun . x))
>
> instead of having to write
>
> (lambda ( . x) (apply fun x))
>
> I assume eval is not supposed to try dealing with dotted lists?

The problem is that (f . (g x y)) is equivalent to (f g x y).
Therefore, while Scheme could in theory support procedure calls with a
dotted tail that happened to be an atom, it would do something rather
different and confusing if the dotted tail was itself a procedure/macro
call.

    Mark



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 15:36 ` Mark H Weaver
@ 2012-02-21 15:59   ` David Kastrup
  2012-02-21 16:05     ` David Kastrup
  2012-02-21 17:23     ` Mark H Weaver
  0 siblings, 2 replies; 9+ messages in thread
From: David Kastrup @ 2012-02-21 15:59 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> David Kastrup <dak@gnu.org> writes:
>> I guess my "real" problem is that I'd like to do call wrapping by writing
>>
>> (lambda ( . x) (fun . x))
>>
>> instead of having to write
>>
>> (lambda ( . x) (apply fun x))
>>
>> I assume eval is not supposed to try dealing with dotted lists?
>
> The problem is that (f . (g x y)) is equivalent to (f g x y).
> Therefore, while Scheme could in theory support procedure calls with a
> dotted tail that happened to be an atom, it would do something rather
> different and confusing if the dotted tail was itself a procedure/macro
> call.

A list in dotted tail position is evaluated via (map ... eval) rather
than (eval ...).  I don't see much of a problem with that.

It works fine for () as one can see:
guile> (+ . ())
0
guile> 

So why not for others?

-- 
David Kastrup




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 15:59   ` David Kastrup
@ 2012-02-21 16:05     ` David Kastrup
  2012-02-21 17:23     ` Mark H Weaver
  1 sibling, 0 replies; 9+ messages in thread
From: David Kastrup @ 2012-02-21 16:05 UTC (permalink / raw)
  To: guile-devel

David Kastrup <dak@gnu.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> David Kastrup <dak@gnu.org> writes:
>>> I guess my "real" problem is that I'd like to do call wrapping by writing
>>>
>>> (lambda ( . x) (fun . x))
>>>
>>> instead of having to write
>>>
>>> (lambda ( . x) (apply fun x))
>>>
>>> I assume eval is not supposed to try dealing with dotted lists?
>>
>> The problem is that (f . (g x y)) is equivalent to (f g x y).
>> Therefore, while Scheme could in theory support procedure calls with a
>> dotted tail that happened to be an atom, it would do something rather
>> different and confusing if the dotted tail was itself a procedure/macro
>> call.
>
> A list in dotted tail position is evaluated via (map ... eval) rather
> than (eval ...).  I don't see much of a problem with that.
>
> It works fine for () as one can see:
> guile> (+ . ())
> 0
> guile> 
>
> So why not for others?

I'll answer this a bit myself.  Well, it does work for other lists.
Cough, cough.  The question is why it doesn't for non-lists.
If (f . x) was supposed to be equivalent to (apply f x), then x would
need to be evaluated.  In (+ . ()), () itself is _not_ being evaluated.
So this would be new behavior, and at least different from that of the
non-pair ().

I'm still not convinced that it would be a bad idea...

-- 
David Kastrup




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 15:59   ` David Kastrup
  2012-02-21 16:05     ` David Kastrup
@ 2012-02-21 17:23     ` Mark H Weaver
  2012-02-21 18:05       ` David Kastrup
  2012-02-21 20:31       ` Neil Jerram
  1 sibling, 2 replies; 9+ messages in thread
From: Mark H Weaver @ 2012-02-21 17:23 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:

> Mark H Weaver <mhw@netris.org> writes:
>
>> David Kastrup <dak@gnu.org> writes:
>>> I guess my "real" problem is that I'd like to do call wrapping by writing
>>>
>>> (lambda ( . x) (fun . x))
>>>
>>> instead of having to write
>>>
>>> (lambda ( . x) (apply fun x))
>>>
>>> I assume eval is not supposed to try dealing with dotted lists?
>>
>> The problem is that (f . (g x y)) is equivalent to (f g x y).
>> Therefore, while Scheme could in theory support procedure calls with a
>> dotted tail that happened to be an atom, it would do something rather
>> different and confusing if the dotted tail was itself a procedure/macro
>> call.
>
> A list in dotted tail position is evaluated via (map ... eval) rather
> than (eval ...).  I don't see much of a problem with that.

No, it's worse than that.  I think you failed to understand my point, so
let me try again.  You propose that (f . x) should be equivalent to
(apply f x).  Therefore, (f . (g x y)) should also be equivalent to
(apply f (g x y)).

However, (f . (g x y)) is read as (f g x y), so it's impossible for
'eval' to distinguish these two cases.  Unfortunately, (f g x y) has a
very different meaning than (apply f (g x y)).  The first means to apply
'f' to three arguments.  The second means to apply 'g' to two arguments,
and then apply 'f' to the list of arguments resulting from (g x y).

To make this more concrete, suppose 'f' is 'vector and 'g' is 'list':

  (vector . (list 1 2))

If we were to adopt your proposal, users would naturally expect this to
evaluate to #(1 2).  However, the evaluator sees (vector list 1 2) and
thus produces a vector of three elements: #(#<procedure list _> 1 2).

In summary, your proposed syntax could only be detected if the dotted
tail happened to be an atom.

Scheme has a very useful property which your proposed syntax would
destroy: any valid expression can be substituted for any other valid
expression, and the result has the same meaning except for the
substitution.  This property is desirable for many reasons.  Users
should be able to freely substitute expressions (possibly using a global
find/replace operation, or via macros) without changing the meaning of
the resulting expressions in surprising ways.

Does this make sense?

      Mark



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 17:23     ` Mark H Weaver
@ 2012-02-21 18:05       ` David Kastrup
  2012-02-22  0:41         ` Mark H Weaver
  2012-02-21 20:31       ` Neil Jerram
  1 sibling, 1 reply; 9+ messages in thread
From: David Kastrup @ 2012-02-21 18:05 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> David Kastrup <dak@gnu.org> writes:
>>
>> A list in dotted tail position is evaluated via (map ... eval) rather
>> than (eval ...).  I don't see much of a problem with that.
>
> No, it's worse than that.  I think you failed to understand my point,
> so let me try again.  You propose that (f . x) should be equivalent to
> (apply f x).

When x is not a pair or ().

> Therefore, (f . (g x y)) should also be equivalent to (apply f (g x
> y)).

But (g x y) is a pair.

> To make this more concrete, suppose 'f' is 'vector and 'g' is 'list':
>
>   (vector . (list 1 2))

(list 1 2) is a pair (with the car list and the cdr (1 2)).

> If we were to adopt your proposal, users would naturally expect this to
> evaluate to #(1 2).  However, the evaluator sees (vector list 1 2) and
> thus produces a vector of three elements: #(#<procedure list _> 1 2).

Sure.

> In summary, your proposed syntax could only be detected if the dotted
> tail happened to be an atom.

() is an atom, but it is already treated differently.

> Scheme has a very useful property which your proposed syntax would
> destroy: any valid expression can be substituted for any other valid
> expression, and the result has the same meaning except for the
> substitution.

guile> (display . (close (current-output-port)))
#<primitive-procedure close>guile> 

Now try

(define x (close (current-output-port)))
(display . x)

Good luck.  The context already decides what a valid expression is.  Not
everything looking like one is treated like one.

-- 
David Kastrup



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 17:23     ` Mark H Weaver
  2012-02-21 18:05       ` David Kastrup
@ 2012-02-21 20:31       ` Neil Jerram
  1 sibling, 0 replies; 9+ messages in thread
From: Neil Jerram @ 2012-02-21 20:31 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: David Kastrup, guile-devel

Mark H Weaver <mhw@netris.org> writes:

> However, (f . (g x y)) is read as (f g x y), so it's impossible for
> 'eval' to distinguish these two cases.  Unfortunately, (f g x y) has a
> very different meaning than (apply f (g x y)).  The first means to apply
> 'f' to three arguments.  The second means to apply 'g' to two arguments,
> and then apply 'f' to the list of arguments resulting from (g x y).

Thanks, Mark.  I've often wondered the same thing as David, so I
appreciate your explanation.

        Neil



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-21 18:05       ` David Kastrup
@ 2012-02-22  0:41         ` Mark H Weaver
  2012-02-22  9:06           ` David Kastrup
  0 siblings, 1 reply; 9+ messages in thread
From: Mark H Weaver @ 2012-02-22  0:41 UTC (permalink / raw)
  To: David Kastrup; +Cc: guile-devel

David Kastrup <dak@gnu.org> writes:

>> Scheme has a very useful property which your proposed syntax would
>> destroy: any valid expression can be substituted for any other valid
>> expression, and the result has the same meaning except for the
>> substitution.
>
> guile> (display . (close (current-output-port)))
> #<primitive-procedure close>guile> 
>
> Now try
>
> (define x (close (current-output-port)))
> (display . x)

Admittedly I could have been more clear, but I certainly didn't mean to
imply that anything that _looks_ like a valid expression can be
replaced.  That would be absurd.

What I meant is that any _subexpression_ can be replaced with any other
valid expression, without changing the meaning of the program in any
other way.  Whether something is a subexpression depends on its
_position_ within the larger expression.

In (display close (current-output-port)), even if you write it
confusingly in dotted-tail notation, (close (current-output-port)) is
_not_ a subexpression, because it is not in subexpression position.

The only advantage I see to this proposed syntax is that in some
restricted cases it is more aesthetically pleasing.  I suspect that most
experienced Schemers have at some point wondered why dotted-tail
notation is not allowed in procedure calls.  I certainly have, but upon
further consideration I became convinced that the pitfalls of adopting
such an ambiguous and potentially confusing syntax far outweigh the
advantages.

    Thanks,
      Mark



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Dotted pair call argument
  2012-02-22  0:41         ` Mark H Weaver
@ 2012-02-22  9:06           ` David Kastrup
  0 siblings, 0 replies; 9+ messages in thread
From: David Kastrup @ 2012-02-22  9:06 UTC (permalink / raw)
  To: guile-devel

Mark H Weaver <mhw@netris.org> writes:

> David Kastrup <dak@gnu.org> writes:
>
>>> Scheme has a very useful property which your proposed syntax would
>>> destroy: any valid expression can be substituted for any other valid
>>> expression, and the result has the same meaning except for the
>>> substitution.
>>
>> guile> (display . (close (current-output-port)))
>> #<primitive-procedure close>guile> 
>>
>> Now try
>>
>> (define x (close (current-output-port)))
>> (display . x)
>
> Admittedly I could have been more clear, but I certainly didn't mean to
> imply that anything that _looks_ like a valid expression can be
> replaced.  That would be absurd.

Exactly.

> What I meant is that any _subexpression_ can be replaced with any other
> valid expression, without changing the meaning of the program in any
> other way.

So the solution would be to not call dotted pair endings of argument
lists a "subexpression", and everybody will be happy.

> Whether something is a subexpression depends on its _position_ within
> the larger expression.

Yes.  That's the point.  The dotted list end is a specific position.
Not "subexpression" position.  If a list is there, it is evaluated
element by element.  If a non-list is there, we get an error.  Instead,
I prefer evaluating it and using the evaluated result, whatever it may
be, as the argument list tail.  Personally, I would not even demand
actual argument lists to be proper lists as long as the declared
argument list is a dotted list as well: you can still match arguments
then.

> The only advantage I see to this proposed syntax is that in some
> restricted cases it is more aesthetically pleasing.

apply can't handle improper lists either.

> I suspect that most experienced Schemers have at some point wondered
> why dotted-tail notation is not allowed in procedure calls.  I
> certainly have, but upon further consideration I became convinced that
> the pitfalls of adopting such an ambiguous and potentially confusing
> syntax far outweigh the advantages.

Nothing that is currently valid would change its meaning.

-- 
David Kastrup




^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-02-22  9:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-21 14:03 Dotted pair call argument David Kastrup
2012-02-21 15:36 ` Mark H Weaver
2012-02-21 15:59   ` David Kastrup
2012-02-21 16:05     ` David Kastrup
2012-02-21 17:23     ` Mark H Weaver
2012-02-21 18:05       ` David Kastrup
2012-02-22  0:41         ` Mark H Weaver
2012-02-22  9:06           ` David Kastrup
2012-02-21 20:31       ` Neil Jerram

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).