guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: cond clause does not allow definitions


From: Maxime Devos
Subject: RE: cond clause does not allow definitions
Date: Thu, 23 May 2024 00:12:02 +0200

>but it is allowed in else clause:
>scheme@(guile-user)> (cond (else (define x 7) x))
>$4 = 7
>
>not really logic

Probably in the implementation of ‘cond’, (cond (else X)) reduces to ‘X’.

It’s tricky to ensure the same behaviour here as is the case when there is more 
than only the ‘else’ clause – without tail-calling, you could use 
‘call-with-values’ in the macro to artificially make an expression context 
etc., but ‘cond’ needs to tail-call for X.

If someone wishes to implement this, I would propose defining some new syntax 
‘begin-expression’ (like ‘begin’, but instead of splicing, it interprets things 
as a bunch of expressions to evaluate in-order, and with the last expression in 
tail-position). Would probably be needed to be implemented as a primitive.

Then, ‘(cond (else X))’ could be implemented as (begin-expression X).

The documentation complains a bit about how ‘begin’ does both splicing and this 
‘begin-expression’, but 'begin’ can be split! (At least, I think so, it has 
been a while since I read that part.)

>It is allowed in Kawa and Racket but they are not scheme references
the R5RS and R7RS talk about 'clause' without more information

I don’t know what the standard says about this.

>is it normal for Guile to consider clause for cond to be an expression
context and not a definition context?

Personally, I don’t care whether something is ‘normal’, whatever that’s 
supposed to mean. What I would care about, is whether the implementation 
matches the documentation, whether the documentation is complete (even saying 
“It is unspecified whether [this] or [that].” would suffice) and whether the 
(documented) semantics is desired, useful, convenient and consistent with 
relevant standards and conventions.

In this case, not all of these are satisfied.

>should not be better to consider definition context? that would allow more
possibilities.

That would be possible – (cond (a x) ...) could be interpreted as (cond (a (let 
() x)) ...) instead.

However, I don’t think it has the semantics you desire. Some time ago, you 
asked questions  along the lines of making a macro ‘define-block’ that allows 
doings things like

(define (f)
  (if blah
      (define-block foo 1)
      (define-block foo 2))
  [do things with foo here])

but that’s not how scoping, macros and in particular ‘let’ works in Scheme, as 
mentioned there.

Personally, I think implementing ‘cond’ as the cond+let stuff mentioned above 
is a bit risky w.r.t. misunderstanding scoping, consider for example:

(define (f x)
  (define y x)
  (cond ((square? x) (define y (sqrt x)) (pk “took a square root”))
             [more branches here])
 y)

which would silently do the wrong thing (unless you enable warnings for 
shadowing, but you can do neat things with shadowing – you can write pure code 
in a somewhat imperative style (*)).

Best regards,
Maxime Devos

(*)  See, e.g., 
https://git.gnunet.org/gnunet-scheme.git/tree/gnu/gnunet/config/parser.scm, 
where ‘let^’ can do (if X (return Y)) and ‘continue’ without let/ec (not an use 
of shadowing but sounds like something you may be interested in). On line 
https://git.gnunet.org/gnunet-scheme.git/tree/gnu/gnunet/config/parser.scm#n481 
and 485, you can see how shadowing is used as a replacement of mutation.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]