hi
Is there a way to return "nothing"? so that : (list nothing 1 2 3 nothing 4 5 6) ; => (1 2 3 4 5 6)
I asked the same question on "comp.lang.scheme", but someone says it can't be done. Is this true?
;; (list (if (> 1 2) 3) (if (> 1 2) 3 nil)) ; -> (#!void ())
both "void" and '() are not exactly the same as "absolutely nothing". It would helps a lot if I can code something like that.
Thanks.
Afficher les réponses par date
dillo gimp wrote:
hi
Is there a way to return "nothing"? so that : (list nothing 1 2 3 nothing 4 5 6) ; => (1 2 3 4 5 6)
I asked the same question on "comp.lang.scheme", but someone says it can't be done. Is this true?
;; (list (if (> 1 2) 3) (if (> 1 2) 3 nil)) ; -> (#!void ())
both "void" and '() are not exactly the same as "absolutely nothing". It would helps a lot if I can code something like that.
Scheme is not Perl with it's autosplicing "list contexts". But it has a syntax for this, quasiquote and unquote-splicing:
`(,@(if (> 1 2) (list 3) '()) ...)
e.g. always return lists from the producer then splice it explicitely.
It depends on the context whether other solutions are appropriate.
If you're producing lists recursively and want a flat result, for example, the clean approach is to feed the tail of the result to the inner invocations as their starting/tail value (that's more efficient than creating the sublists with '() as tail value and then appending the lists afterwards (as the above unquote-splicing does), and is still quite logical). Use the generic fold / fold-right functions for this, or write functions which take an #!optional (tail '()).
When writing macros I also sometimes flatten the list afterwards, I've even written a combined flat-append-strings function for this (for an example, see http://scheme.mine.nu/gambit/scratch/flat/cj-c-util.scm). This works well when you have the same object type only in the list, like strings.
SXML ignores #f and '() when serializing (at least my serializer does so), so you can just output those values without worrying.
Christian.
On 4/29/07, Christian Jaeger christian@pflanze.mine.nu wrote:
dillo gimp wrote:
hi
Is there a way to return "nothing"? so that : (list nothing 1 2 3 nothing 4 5 6) ; => (1 2 3 4 5 6)
I asked the same question on "comp.lang.scheme", but someone says it can't be done. Is this true?
;; (list (if (> 1 2) 3) (if (> 1 2) 3 nil)) ; -> (#!void ())
both "void" and '() are not exactly the same as "absolutely nothing". It would helps a lot if I can code something like that.
Scheme is not Perl with it's autosplicing "list contexts". But it has a syntax for this, quasiquote and unquote-splicing:
`(,@(if (> 1 2) (list 3) '()) ...)
e.g. always return lists from the producer then splice it explicitely.
It depends on the context whether other solutions are appropriate.
Is it a good idea hacking the interpreter to automatically ignore all <#void>? I don't know if <#void> servers any purpose... "length" actually counts <#void> as well. There are legitmate reason for returning nothing, either because the caller has been written yet, or that it would be ugly to push the logic to the caller.
I'm doing polynomial addition and it's possible the term could be eliminated: If I push the logic to the caller, the code looks ugly. Besides, the code hasn't been written yet. It would be better for the language to support it, instead of people each hacking a different interpreter...
(define (TaddT x y) (if (equal? (cadr x) (cadr y)) (if (not (= (+ (car x) (car y)) 0)) (list (list (+ (car x) (car y)) (cadr x))) '() ) '() ) ) `(aaa ,@(TaddT '(2 (1 2 3)) '(3 (4 5 6))) aaa) (length `(aaa ,@(TaddT '(2 (1 2 3)) '(3 (4 5 6))) aaa)) `(aaa ,@(TaddT '(2 (1 2 3)) '(3 (1 2 3))) aaa) (length `(aaa ,@(TaddT '(2 (1 2 3)) '(3 (1 2 3))) aaa)) `(aaa ,@(TaddT '(-3 (1 2 3)) '(3 (1 2 3))) aaa) (length `(aaa ,@(TaddT '(-3 (1 2 3)) '(3 (1 2 3))) aaa))
If you're producing lists recursively and want a flat result, for example, the clean approach is to feed the tail of the result to the inner invocations as their starting/tail value (that's more efficient than creating the sublists with '() as tail value and then appending the lists afterwards (as the above unquote-splicing does), and is still quite logical). Use the generic fold / fold-right functions for this, or write functions which take an #!optional (tail '()).
When writing macros I also sometimes flatten the list afterwards, I've even written a combined flat-append-strings function for this (for an example, see http://scheme.mine.nu/gambit/scratch/flat/cj-c-util.scm). This works well when you have the same object type only in the list, like strings.
SXML ignores #f and '() when serializing (at least my serializer does so), so you can just output those values without worrying.
Christian.
dillo gimp wrote:
Is it a good idea hacking the interpreter to automatically ignore all <#void>?
No, I don't think so.
I don't know if <#void> servers any purpose...
It's #!void, btw (with exclamation mark).
It's a value that you can't rely on. The "unspecified" value. I consider it an important sign of code which doesn't return a value when it should, like forgetting the else branch in an (if foo "bar") or similar. Using it for the purpose of specifying something (namely "no value") would be wrong since that would be a valid usage then, not a bug anymore.
You should use '() for that purpose and write the receiver so that he knows to expect a list.
You know, even perl differentiates between splicing mode and sublist mode: you add [ ] around a list (or take a reference of an array variable) to make it explicitely an array. There's no way around being explicit or ambiguities will arise. Only in places where certain ambiguity doesn't matter you can get away without (like in my flat-string-append or SXML examples).
The question is rather which syntax you want to use for the purpose of differentiating between the two modi.
"length" actually counts <#void> as well.
Sure, it's an element in the list (holding a "buggy" value, so to say, you want to see that for debugging!).
There are legitmate reason for returning nothing, either because the caller has been written yet, or that it would be ugly to push the logic to the caller.
Usually you choose #f for saying "no object" (kind of like the C null pointer). But if you want to make #f part of the range of valid objects, you should specify your iterface to return a list (maybe of 0 or 1 values).
You know, other lisps only had nil. Scheme went so far as to make two values out of the one: #f for boolean false or "none" in "scalar context", and '() for "none" in list context. Separating #f into yet another two values probably won't do much good, especially since it would make code like (or (maybe-x) (maybe-y) (maybe-z)) more complicated. It's nice to be able to interpret the "missing value" as false. You can use boolean operators for handling branches on missing values.
But nobody told that the missing value should automatically vanish in list context. Even perl doesn't do that, if you return undef, its still inserted into the output. Only if you return (), it vanishes. Same thing with Scheme, you return '() into a context which expects a list, and everything is fine.
A solution which is being used for cases where one wants to be sure that the user checks for the missing value (e.g. throw an exception if he doesn't seem to be prepared for the check), is to expect him to give a function a special value which is then returned as "nothing". See Gambit's table-ref as example.
And there's the solution of using "manual CPS style" and explicitely pass separate continuations that the function should call depending on the outcome.
(define (frob val success failure) .... (if was-successful (success result) (failure)))
I'm doing polynomial addition and it's possible the term could be eliminated: If I push the logic to the caller, the code looks ugly. Besides, the code hasn't been written yet. It would be better for the language to support it, instead of people each hacking a different interpreter...
(define (TaddT x y) (if (equal? (cadr x) (cadr y)) (if (not (= (+ (car x) (car y)) 0)) (list (list (+ (car x) (car y)) (cadr x))) '() ) '() ) )
Could you use #f for the purpose? Maybe your case is special in that you could safely return #f, but insert the value into list context. What about:
(define (TaddT x y) (and (equal? (cadr x) (cadr y)) (not (= (+ (car x) (car y)) 0)) (list (+ (car x) (car y)) (cadr x))))
(define (list* . args) (filter values args))
`(aaa ,@(TaddT '(2 (1 2 3)) '(3 (4 5 6))) aaa)
(list* 'aaa (TaddT '(2 (1 2 3)) '(3 (4 5 6))) 'aaa)
But maybe it would really be nicer to write it using the fold approach? (Building results by prepending them onto a list of results can in some way really make for code that's nice and logical. You're folding your tree together to an output list.) I don't have the time to check out what you're doing exactly.
Christian.
(hoping indentation is being preserved this time)
Is there a way to return "nothing"? so that : (list nothing 1 2 3 nothing 4 5 6) ; => (1 2 3 4 5 6)
I was last week wondering about something really close to thise question : Is it possible to write a macro that expands to nothing ? (ideally, a portable way to do it)
In C, one can write #define NOTHING NOTHING printf NOTHING (NOTHING "%d\n",x);
So, I naively tried (define-syntax nothing (syntax-rules() ((nothing)))) But it wouldn't compile.
The aim is to embed code as a macro in another file, and with the right parser, to be able to fetch back this data (no, it's not steganography, just Scheme code annotation in Scheme) Roughly speaking, I want to write comments in scheme (that would be parsed by the REPL, and stripped by the macro)
Adrien
Adrien Pierard wrote:
I was last week wondering about something really close to thise question : Is it possible to write a macro that expands to nothing ? (ideally, a portable way to do it)
I think the best way is to return '(begin) from the macro (that's what I do and also many other people; other solutions include #!void (syntax not portable), #f (but doesn't hint as well at bugs, or similar values).
Christian.
Adrien Pierard wrote:
The aim is to embed code as a macro in another file, and with the right parser, to be able to fetch back this data (no, it's not steganography, just Scheme code annotation in Scheme) Roughly speaking, I want to write comments in scheme (that would be parsed by the REPL, and stripped by the macro)
Maybe I didn't read your mail closely enough. Seems like you might want to strip sexprs from parts where Scheme doesn't expect code, so even turning them into (begin) wouldn't work.
If that's the case, there are one or two other things you could do:
- maybe just make the whole form a macro then remove the comment stuff? (e.g. wrap define and lambda in a macro to remove annotations on function arguments; I admit that I've been looking for nice ways to extend define and lambda syntax in an extendable way since I've started using Scheme, so that e.g. two libraries could both add their own set of extensions; probably staging would be the right thing (alternatively emulate staging through some kind of module parametrization of the first stage library and renaming the macros of the second stage on import to achieve the same thing over intermediate distinct names). (Does some macro system already support staging? Do you even know what I'm talking about?.)
- you could write your own code expander; Gambit has hooks for this. I've done this for using "namespacing" prefixes to generate SXML templates, so that e.g.
(define (doc firstname) (html:html (html:body (html:p (string-append "Hello " firstname))))
would be expanded to
(define (doc firstname) `(html (body (p ,(string-append "Hello " firstname))))
(it's in my also-to-be-released cj-sxmltemplates module).
Christian.