Re: Question about how to check a symbol is bound

2023-06-29 Thread Peter Bex
On Wed, Jun 28, 2023 at 09:32:36PM +0200, felix.winkelm...@bevuta.com wrote:
> But I still think that keeping an expansion/compile-time registry and
> accessing it using procedure macros (via "strip-syntax"ed identifiers
> to drop all renaming artifacts) is a possible solution.

I agree, that's how I would approach it too.
I don't think you need to strip-syntax everything, though.

Alaric, if you provide a stripped down, *actually working* (except for
the bit you're struggling with, of course) piece of code I might be
able to help you there.

Cheers,
Peter 


signature.asc
Description: PGP signature


Re: Question about how to check a symbol is bound

2023-06-28 Thread felix . winkelmann
> On 28/06/2023 14:09, felix.winkelm...@bevuta.com wrote:
> >>
> >> (define-object-type bar
> >> (field-1 name-of-library#foo)
> >> (field-2 name-of-other-library#some-other-type))
> >>
> >> ...even though calling symbol-value on those symbols at run time works
> >> just fine. It seems that the symbols imported into the environment at
> >> macro expansion time are handled differently in some way.
> >>
> >
> > I guess during expansion identifiers are renamed to some internal gensym
> > and thus not accessible by name (which is the whole point of a hygienic
> > macro system). Could you not register the "foo" type in a expansion time
> > hash table?
>
> Alas, the requirement is that things like "foo" are part of the lexical
> environment - so can be imported from modules, renamed, be hidden inside
> local scopes, all that stuff!
>

I guess some macro wizard will come up with a way to do this.
But I still think that keeping an expansion/compile-time registry and
accessing it using procedure macros (via "strip-syntax"ed identifiers
to drop all renaming artifacts) is a possible solution.


felix




Re: Question about how to check a symbol is bound

2023-06-28 Thread Alaric Snell-Pym

On 28/06/2023 14:09, felix.winkelm...@bevuta.com wrote:


I guess during expansion identifiers are renamed to some internal gensym
and thus not accessible by name (which is the whole point of a hygienic
macro system).


Oh, and as a side thing, I don't think this is exactly "unhygienic". 
Well, the thing I'm trying to do is hygienic, and I'm just being forced 
to explore unhygienic techniques to try and recreate that hygienic solution.


After all, we can do:

(define-for-syntax foo 123)

(define-syntax ...
  ... foo ...)

...and get 123 out of foo at macro expansion time.

What I want to be able to do is:

(define-inner-thing X 123)

(define-outer-thing Y (X))

...and have define-outer-thing's macro expander be able to get 123 from 
X. It doesn't really need to know about X as a symbol, and all this 
symbol-value nastiness is just a way to try and convert from X passed to 
it as a symbol to the value of X, which I'd rather do in a hygienic 
manner - if I could!


Of course, we can do something like this:

(define-syntax define-inner-thing
 (ir-macro-transformer
   ...
 `(define-syntax ,NAME
   (syntax-rules (context1 context2)
 ((_ context1) ,generated-code-for-context1)
 ((_ context2) ,generated-code-for-context2
  ...)


(define-syntax define-outer-thing
  (syntax-rules ()
((define-outer-thing NAME ((FIELD TYPE) ...))
   ...(TYPE context1)...
   ...(TYPE context2)...)))

...and thereby have define-inner-thing use arbitrary low-level macros to 
generate arbitrary code snippets and wrap them in a macro binding, that 
define-outer-thing can then pull out by invoking the macro. But 
define-outer-thing can only splice the generated code into its 
expansion, and not do things like combined generated ssql snippets and 
ssql->sql them at macro expansion time, which would be nice: if I follow 
that path I'll need to expand to code that calls a pure function on 
constant arguments at runtime.




felix



--
Alaric Snell-Pym   (M0KTN neé M7KIT)
http://www.snell-pym.org.uk/alaric/



OpenPGP_signature
Description: OpenPGP digital signature


Re: Question about how to check a symbol is bound

2023-06-28 Thread Alaric Snell-Pym

On 28/06/2023 14:09, felix.winkelm...@bevuta.com wrote:


(define-object-type bar
(field-1 name-of-library#foo)
(field-2 name-of-other-library#some-other-type))

...even though calling symbol-value on those symbols at run time works
just fine. It seems that the symbols imported into the environment at
macro expansion time are handled differently in some way.



I guess during expansion identifiers are renamed to some internal gensym
and thus not accessible by name (which is the whole point of a hygienic
macro system). Could you not register the "foo" type in a expansion time
hash table?


Alas, the requirement is that things like "foo" are part of the lexical 
environment - so can be imported from modules, renamed, be hidden inside 
local scopes, all that stuff!




felix



Thanks,

--
Alaric Snell-Pym   (M0KTN neé M7KIT)
http://www.snell-pym.org.uk/alaric/



OpenPGP_signature
Description: OpenPGP digital signature


Re: Question about how to check a symbol is bound

2023-06-28 Thread felix . winkelmann
>
> (define-object-type bar
>(field-1 name-of-library#foo)
>(field-2 name-of-other-library#some-other-type))
>
> ...even though calling symbol-value on those symbols at run time works
> just fine. It seems that the symbols imported into the environment at
> macro expansion time are handled differently in some way.
>

I guess during expansion identifiers are renamed to some internal gensym
and thus not accessible by name (which is the whole point of a hygienic
macro system). Could you not register the "foo" type in a expansion time
hash table?


felix




Re: Question about how to check a symbol is bound

2023-06-28 Thread Alaric Snell-Pym

On 23/06/2023 14:35, Kon Lovett wrote:

(symbol-value foo #f)
Error: unbound variable: foo


#;2> (symbol-value 'foo #f)
#f

(symbol-value foo #f) is asking for the symbol-value of the derefed variable 
`foo’


Does anybody have any tips for using symbol-value at macroexpansion time?

I am trying to port a library from chicken 4 to 5, that lets users write 
something along these lines (full details available on request, I'm 
trying to just extract and summarise the important parts here):


(define-custom-type foo ...some metadata...)

And then later:

(define-object-type bar ...list of fields and types...)

Eg:

  ;; A foo contains three strings
(define-custom-type foo string string string)

(define-object-type bar
  (field-1 foo)
  (field-2 some-other-type))

Now, the implementation of define-object-type needs to be able to 
examine the contents of the foo custom-type at macro expansion time (to 
give a bit more detail, this is a wrapper around a SQL database and it 
needs to know the structure of everything to pre-generate SQL queries, 
create table statements, and so on)


I've had partial success with making define-custom-type expand into a 
define-for-syntax that wraps a processed form of its metadata into a 
value and binds it to the symbol "foo", then making define-object-type 
find the type name symbols and call symbol-value on them - but this 
doesn't work if the type name is imported from a library. Even if I make 
the user write:


(define-object-type bar
  (field-1 name-of-library#foo)
  (field-2 name-of-other-library#some-other-type))

...even though calling symbol-value on those symbols at run time works 
just fine. It seems that the symbols imported into the environment at 
macro expansion time are handled differently in some way.


Is there a way to do what I want?

I'm also working on an alternate approach - where define-custom-type 
defines a macro that actually embeds the parts of the implementation of 
define-object-type that depend on the structure and make 
define-object-type invoke that macro as part of its expansion - but it's 
so inside out it makes my head hurt so I'm not 100% sure it'll be 
possible yet (at the very least, it might leave some string/list 
concatenation to run time, which is disappointing). And it's a sad 
violation of abstraction boundaries between define-custom-type and 
define-object-type. Hey ho.


PS: Hi everyone! I'm still alive!

--
Alaric Snell-Pym   (M0KTN neé M7KIT)
http://www.snell-pym.org.uk/alaric/



OpenPGP_signature
Description: OpenPGP digital signature


Re: Question about how to check a symbol is bound

2023-06-23 Thread Kon Lovett



> On Jun 22, 2023, at 9:07 PM, Pan Xie  wrote:
> 
> Hello
> 
> I am new to CHICKEN scheme and here is a (very) quick question of how to 
> check whether a symbol is bound.
> 
> I know it doable but I can't find the way.
> 
> I don't find the methods from the main CHICKEN manual document. Then I import 
> the "symbol-value-utils" module. I believe the "unbound?" or "symbol-value" 
> will do what I want, but to my surprise they does NOT:
> 
> I expect `symbol-value' will give me value of a symbol, but it will throw 
> exception for an
> undefined symbol, even I provide the default value:
> 
> (symbol-value foo #f)
> Error: unbound variable: foo

#;2> (symbol-value 'foo #f)
#f

(symbol-value foo #f) is asking for the symbol-value of the derefed variable 
`foo’

> 
> I expect (symbol-value (string->symbol "list")) will give me the list 
> procedure, but what I get is '#f'
> 
> (symbol-value (string->symbol "list"))
> #f

#;6> (symbol-value (string->symbol (string-append "scheme" "#" "list")))
#

> 
> I expect (unbound? foo) will return True value, but it just throw exception.

#;7> (unbound? ‘foo)
#t

#;9> (unbound? (string->symbol (string-append "scheme" "#" "list")))
#f

> 
> Does CHICKEN scheme provide facilities that make user check whether arbitrary 
> symbol is bound or get its value, just like the `boundp' or `symbol-value' in 
> Common Lisp?
> 
> Thanks
> Pan
> 
> 




Re: Question about how to check a symbol is bound

2023-06-23 Thread Thomas Chust
Hello,

if you are looking for record introspection capabilities, I would recommend
looking into SRFI-99[1], which combines static structure definition and
dynamic reflection APIs. You're example could look like this:

(import
(chicken format)
srfi-42
srfi-99)

(define-record-type egg-info
make-egg-info egg-info?
name author desc)

(define (print-record/fields r)
(define rtd (record-rtd r))
(do-ec (: f (rtd-field-names rtd))
(format #t "~a: ~a~%" f ((rtd-accessor rtd f) r

(print-record/fields
(make-egg-info
"F-operator"
"Kon Lovett"
"Shift/Reset Control Operators"))

Ciao,
Thomas

-- 
[1]: https://srfi.schemers.org/srfi-99/srfi-99.html


Am Fr., 23. Juni 2023 um 10:03 Uhr schrieb Pan Xie :

> #+begin_quote
> Perhaps if you can explain why you need to know if a symbol is bound or
> unbound, we might be able to help you better achieve your goal.
> #+end_quote
>
>
> For example, if I want to do things shown in following codes, it is useful
> to get the
> interned symbols from their names and also get their bound procedures:
>
>   (define-record egg-info
> name author desc)
>
>   (define (show-egg-info egg)
> (define (symbol-value sym)
>   (##sys#slot sym 0))
>
> (define (getter field-name)
>   (symbol-value
>(string->symbol
> (format #f "egg-info-~a"
> field-name
>
> (let ((fields '(name author desc)))
>   (for-each
>(lambda (f)
>  (format #t "~a: ~a~%"
>  f
>  ((getter f) egg)))
>fields)))
>
>   (show-egg-info (make-egg-info
>   "F-operator"
>   "Kon Lovett"
>   "Shift/Reset Control Operators"))
>
> I think it is a very common idiom in languages from Lisp family. So it is
> important to know
> how to check symbol is bound and get its value. Every scheme
> implementation means for
> business seriously should have the ability.
>
> Thanks
> Pan
>
>
> On 6/23/23 15:40, Peter Bex wrote:
> > On Fri, Jun 23, 2023 at 03:32:38PM +0800, Pan wrote:
> >> Ah, that make sense. It seems I can just use the '##sys#slot' procedure
> to
> >> accomplish all that tasks.
> > Please don't use ##sys#slot unless you know what you're doing - the
> > procedure is unsafe and will cause segmentation faults when used on
> > non-block objects.  Anything that starts with ##sys# or ##core# etc
> > is intentionally undocumented because it's not meant for user code.
> >
> >> Would you please elaborate about the "transformed
> >> name"?  I see there are codes reference symbols like "##sys#slot" or
> >> "scheme#list", but I can't find document describe them. Is there any
> >> document I can look into? More specifically, how can I transfer "list"
> to
> >> "scheme#list"? Is there procedure can do that?
> > scheme#list is the fully qualified symbol that means it's the "list"
> > procedure from the "scheme" module.  If you do "(import scheme)" and then
> > just use "list" without prefix, it will get rewritten under the hood.
> >
> > Again, this is an implementation detail and not meant to be used
> > directly.
> >
> > Perhaps if you can explain why you need to know if a symbol is bound or
> > unbound, we might be able to help you better achieve your goal.
> >
> > Cheers,
> > Peter
>
>


Re: Question about how to check a symbol is bound

2023-06-23 Thread Peter Bex
On Fri, Jun 23, 2023 at 04:01:40PM +0800, Pan Xie wrote:
> For example, if I want to do things shown in following codes, it is useful to 
> get the
> interned symbols from their names and also get their bound procedures:

...[code elided]...

> I think it is a very common idiom in languages from Lisp family. So it is 
> important to know
> how to check symbol is bound and get its value. Every scheme implementation 
> means for
> business seriously should have the ability.

That's a bit of a roundabout way of doing things - you're defining a
static record type and then dynamically accessing the fields, which kind
of defeats the point of defining the fields statically.  Your code
*almost* amounts to doing 

 (define (getter f)
   (eval (symbol-append 'egg-info f)))

If the fields are supposed to be dynamic, it'd make more sense to use
a hash table or alist and access the fields that way.

Or, if you insist on using a record type, perhaps a tiny bit of
macrology would help, like so:

 (import (chicken format))

 (define-record egg-info
   name author desc)
 (define (show-egg-info egg)
   (let-syntax ((fields->accessors
 (er-macro-transformer
  (lambda (e r c)
(let ((fields (cdr e))
  (%list (r 'list))
  (%cons (r 'cons)))
  `(,%list ,@(map (lambda (f)
`(,%cons ',f ,(symbol-append 'egg-info- 
f)))
  fields)))
 (for-each (lambda (name)
 (let ((field-name (car name))
   (field-accessor (cdr name)))
  (format #t "~a: ~a~%"
  field-name
  (field-accessor egg
   (fields->accessors name author desc

 (show-egg-info (make-egg-info
 "F-operator"
 "Kon Lovett"
 "Shift/Reset Control Operators"))

This way, you're dynamically generating the code to access the record
type statically and you don't have to do low-level symbol groveling.

In Scheme, identifiers are typically not considered "global" like in
Common Lisp because of the strong module system - they can be imported
under a different name etc.  For instance, I can make a module in which
the "global" variable "list" means something entirely different.

However, CHICKEN does maintain a global symbol table with fully
qualified symbols.  So scheme#list refers to the "global" list procedure
from the "scheme" module.  But again, that's an implementation detail
you don't want to rely on in general.

Cheers,
Peter


signature.asc
Description: PGP signature


Re: Question about how to check a symbol is bound

2023-06-23 Thread Lassi Kortela

  (define-record egg-info
    name author desc)

  (define (show-egg-info egg)
    (define (symbol-value sym)
  (##sys#slot sym 0))
    (define (getter field-name)
  (symbol-value
   (string->symbol
    (format #f "egg-info-~a"
    field-name
    (let ((fields '(name author desc)))
  (for-each
   (lambda (f)
     (format #t "~a: ~a~%"
     f
     ((getter f) egg)))
   fields)))

  (show-egg-info (make-egg-info
  "F-operator"
  "Kon Lovett"
  "Shift/Reset Control Operators"))


What you're looking for is record inspection (aka introspection). That 
has been standardized in R6RS, but Chicken doesn't have it AFAIK.


The right points of comparison in Common Lisp are:

* slot-value
* slot-boundp
* slot-exists-p

Symbol-value is not a good point of comparison, as it has to do with 
packages, not records. Neither Scheme not CL programmers tend to solve 
problems by poking around the symbol table. It's a last resort.


Your best bet in Scheme as it stands, is to use a hash table or 
association list instead of a record type. Or wrap a hash table in a record.


I think it is a very common idiom in languages from Lisp family. So it 
is important to know

how to check symbol is bound and get its value.


It's not idiomatic at all. It's useful mainly for tools that support 
interactive development, e.g. via REPL or Emacs.




Re: Question about how to check a symbol is bound

2023-06-23 Thread Pan Xie

#+begin_quote
Perhaps if you can explain why you need to know if a symbol is bound or
unbound, we might be able to help you better achieve your goal.
#+end_quote


For example, if I want to do things shown in following codes, it is useful to 
get the
interned symbols from their names and also get their bound procedures:

 (define-record egg-info
   name author desc)
 
 (define (show-egg-info egg)

   (define (symbol-value sym)
 (##sys#slot sym 0))
   
   (define (getter field-name)

 (symbol-value
  (string->symbol
   (format #f "egg-info-~a"
   field-name
   
   (let ((fields '(name author desc)))

 (for-each
  (lambda (f)
(format #t "~a: ~a~%"
f
((getter f) egg)))
  fields)))

 (show-egg-info (make-egg-info
 "F-operator"
 "Kon Lovett"
 "Shift/Reset Control Operators"))

I think it is a very common idiom in languages from Lisp family. So it is 
important to know
how to check symbol is bound and get its value. Every scheme implementation 
means for
business seriously should have the ability.

Thanks
Pan


On 6/23/23 15:40, Peter Bex wrote:

On Fri, Jun 23, 2023 at 03:32:38PM +0800, Pan wrote:

Ah, that make sense. It seems I can just use the '##sys#slot' procedure to
accomplish all that tasks.

Please don't use ##sys#slot unless you know what you're doing - the
procedure is unsafe and will cause segmentation faults when used on
non-block objects.  Anything that starts with ##sys# or ##core# etc
is intentionally undocumented because it's not meant for user code.


Would you please elaborate about the "transformed
name"?  I see there are codes reference symbols like "##sys#slot" or
"scheme#list", but I can't find document describe them. Is there any
document I can look into? More specifically, how can I transfer "list" to
"scheme#list"? Is there procedure can do that?

scheme#list is the fully qualified symbol that means it's the "list"
procedure from the "scheme" module.  If you do "(import scheme)" and then
just use "list" without prefix, it will get rewritten under the hood.

Again, this is an implementation detail and not meant to be used
directly.

Perhaps if you can explain why you need to know if a symbol is bound or
unbound, we might be able to help you better achieve your goal.

Cheers,
Peter




Re: Question about how to check a symbol is bound

2023-06-23 Thread Peter Bex
On Fri, Jun 23, 2023 at 03:32:38PM +0800, Pan wrote:
> Ah, that make sense. It seems I can just use the '##sys#slot' procedure to
> accomplish all that tasks.

Please don't use ##sys#slot unless you know what you're doing - the
procedure is unsafe and will cause segmentation faults when used on
non-block objects.  Anything that starts with ##sys# or ##core# etc
is intentionally undocumented because it's not meant for user code.

> Would you please elaborate about the "transformed
> name"?  I see there are codes reference symbols like "##sys#slot" or
> "scheme#list", but I can't find document describe them. Is there any
> document I can look into? More specifically, how can I transfer "list" to
> "scheme#list"? Is there procedure can do that?

scheme#list is the fully qualified symbol that means it's the "list"
procedure from the "scheme" module.  If you do "(import scheme)" and then
just use "list" without prefix, it will get rewritten under the hood.

Again, this is an implementation detail and not meant to be used
directly.

Perhaps if you can explain why you need to know if a symbol is bound or
unbound, we might be able to help you better achieve your goal.

Cheers,
Peter


signature.asc
Description: PGP signature


Re: Question about how to check a symbol is bound

2023-06-23 Thread Pan
Ah, that make sense. It seems I can just use the '##sys#slot' procedure 
to accomplish all that tasks. Would you please elaborate about the 
"transformed name"?  I see there are codes reference symbols like 
"##sys#slot" or "scheme#list", but I can't find document describe them. 
Is there any document I can look into? More specifically, how can I 
transfer "list" to "scheme#list"? Is there procedure can do that?


On 6/23/23 13:28, Shawn Wagner wrote:
Looks like unbound? and symbol-value take quoted symbols if passing them 
directly: And for list you have to use the transformed name scheme#list


#;2> (unbound? 'x)
#t
#;3> (define x 1)
#;4> (unbound? 'x)
#f
#;5> (symbol-value 'x)
1
#;6> (symbol-value 'scheme#list)
#

On Thu, Jun 22, 2023 at 10:15 PM Pan Xie > wrote:


Hello

I am new to CHICKEN scheme and here is a (very) quick question of
how to
check whether a symbol is bound.

I know it doable but I can't find the way.

I don't find the methods from the main CHICKEN manual document. Then I
import the "symbol-value-utils" module. I believe the "unbound?" or
"symbol-value" will do what I want, but to my surprise they does NOT:

I expect `symbol-value' will give me value of a symbol, but it will
throw exception for an
undefined symbol, even I provide the default value:

(symbol-value foo #f)
Error: unbound variable: foo

I expect (symbol-value (string->symbol "list")) will give me the list
procedure, but what I get is '#f'

(symbol-value (string->symbol "list"))
#f

I expect (unbound? foo) will return True value, but it just throw
exception.

Does CHICKEN scheme provide facilities that make user check whether
arbitrary symbol is bound or get its value, just like the `boundp' or
`symbol-value' in Common Lisp?

Thanks
Pan







Re: Question about how to check a symbol is bound

2023-06-22 Thread Shawn Wagner
Looks like unbound? and symbol-value take quoted symbols if passing them
directly: And for list you have to use the transformed name scheme#list

#;2> (unbound? 'x)
#t
#;3> (define x 1)
#;4> (unbound? 'x)
#f
#;5> (symbol-value 'x)
1
#;6> (symbol-value 'scheme#list)
#

On Thu, Jun 22, 2023 at 10:15 PM Pan Xie  wrote:

> Hello
>
> I am new to CHICKEN scheme and here is a (very) quick question of how to
> check whether a symbol is bound.
>
> I know it doable but I can't find the way.
>
> I don't find the methods from the main CHICKEN manual document. Then I
> import the "symbol-value-utils" module. I believe the "unbound?" or
> "symbol-value" will do what I want, but to my surprise they does NOT:
>
> I expect `symbol-value' will give me value of a symbol, but it will
> throw exception for an
> undefined symbol, even I provide the default value:
>
> (symbol-value foo #f)
> Error: unbound variable: foo
>
> I expect (symbol-value (string->symbol "list")) will give me the list
> procedure, but what I get is '#f'
>
> (symbol-value (string->symbol "list"))
> #f
>
> I expect (unbound? foo) will return True value, but it just throw
> exception.
>
> Does CHICKEN scheme provide facilities that make user check whether
> arbitrary symbol is bound or get its value, just like the `boundp' or
> `symbol-value' in Common Lisp?
>
> Thanks
> Pan
>
>
>


Question about how to check a symbol is bound

2023-06-22 Thread Pan Xie

Hello

I am new to CHICKEN scheme and here is a (very) quick question of how to 
check whether a symbol is bound.


I know it doable but I can't find the way.

I don't find the methods from the main CHICKEN manual document. Then I 
import the "symbol-value-utils" module. I believe the "unbound?" or 
"symbol-value" will do what I want, but to my surprise they does NOT:


I expect `symbol-value' will give me value of a symbol, but it will 
throw exception for an

undefined symbol, even I provide the default value:

(symbol-value foo #f)
Error: unbound variable: foo

I expect (symbol-value (string->symbol "list")) will give me the list 
procedure, but what I get is '#f'


(symbol-value (string->symbol "list"))
#f

I expect (unbound? foo) will return True value, but it just throw exception.

Does CHICKEN scheme provide facilities that make user check whether 
arbitrary symbol is bound or get its value, just like the `boundp' or 
`symbol-value' in Common Lisp?


Thanks
Pan