Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return type of the object #46

Closed
jcubic opened this issue Aug 15, 2021 · 15 comments
Closed

Return type of the object #46

jcubic opened this issue Aug 15, 2021 · 15 comments

Comments

@jcubic
Copy link
Contributor

jcubic commented Aug 15, 2021

I have this function in my interpreter, but it does a lot more since it also returns types for JavaScript objects and also internal implementation objects.

Here is something for R7RS scheme:

(define (type obj)
  (cond ((number? obj) "number")
        ((string? obj) "string")
        ((symbol? obj) "symbol")
        ((vector? obj) "vector")
        ((pair? obj) "pair")
        ((null? obj) "nil")
        ((procedure? x) "procedure")
        ((char? x) "character")
        ((boolean? obj) "boolean")))

Unfortunately, there is no way to test if an object is a record type.

@lassik Should we include functions like this or is it too simple? I think it would be nice to have this function so you don't need to write it yourself and can just copy/paste.

@jcubic
Copy link
Contributor Author

jcubic commented Aug 15, 2021

A similar function is in #42 but that is more to match my implementation.

@lassik
Copy link
Member

lassik commented Aug 16, 2021

Sure, why not. It's a useful procedure. Since we divide the cookbook into sections, it should be quite easy to navigate even with lots of pages.

R7RS section 3.2. "Disjointness of types" lists all the standard predicates:

  • boolean?
  • bytevector?
  • char?
  • eof-object?
  • null?
  • number?
  • pair?
  • port?
  • procedure?
  • string?
  • symbol?
  • vector?

As you noticed, Scheme has no standard type-of procedure. Some implementations may have one, but I don't know what those are.

@jcubic
Copy link
Contributor Author

jcubic commented Aug 16, 2021

@lassik in Guile and Chicken there are no bytevector? is there a way to make the function works if the function is defined and not?

Here is the code now:

(define (type obj)
  (cond ((number? obj) "number")
        ((pair? obj) "pair")
        ((null? obj) "nil")
        ((string? obj) "string")
        ((symbol? obj) "symbol")
        ((vector? obj) "vector")
        ((procedure? obj) "procedure")
        ((port? obj)
         (cond ((input-port? obj) "input-port")
               ((output-port? obj) "output-port")
               (else "unknown-port")))
        ((eof-object? obj) "eof")
        ((char? obj) "character")
        ((boolean? obj) "boolean")))

@APIPLM
Copy link

APIPLM commented Aug 16, 2021

bytevector? is in the register-compiled-module of r7rs along with srfi-4 in the source /chicken-install/r7rs/r7rs.import.scm.

@APIPLM
Copy link

APIPLM commented Aug 16, 2021

Unfortunatly seem like it is not in the document. As running ./chicken-doc bytevector? , the output is

path: (gl-utils bytevector?)

-- procedure:  (bytevector? BYTEVECTOR)

Returns true if `BYTEVECTOR` is a bytevector, false otherwise.

In the search result, there is not the path like (r7rs bytevector?) or (srfi-4 bytevector?)

@lassik
Copy link
Member

lassik commented Aug 16, 2021

bytevector? is in the (scheme base) library in R7RS.

In Chicken, using the r7rs egg with csi -R r7rs, (import (scheme base)) will import bytevector?.

SRFI 4 uses the term u8vector instead of bytevector. (import (srfi 4)) will provide u8vector?. In Chicken, bytevector? is an alias for u8vector?.

@jcubic
Copy link
Contributor Author

jcubic commented Aug 16, 2021

We can include an alternative recipe with define-library.

@APIPLM
Copy link

APIPLM commented Aug 16, 2021

@jcubic It is no needed, what we are talking about is that how chicken implementation bring the symbol bytevector? to in the (scheme base) library in R7RS. I supposed that in Chicken the way csi -R r7rs,(import (scheme base)) is the standard to run any scheme script in R7RS, and that is part of running scheme script in R7RS in the Cookbook

@lassik
Copy link
Member

lassik commented Aug 16, 2021

@APIPLM Search for bytevector? in this file and you'll find the definition.

@APIPLM
Copy link

APIPLM commented Aug 16, 2021

Thanks.@lassik
I just checked that what REPL load so files are almost the same as running (import (scheme base) and (import r7rs). The only different is the loading additional r7rs.so file as running (import r7rs), but in the only file r7rs.scm is almost all about syntax.
So basically in Chicken the standard way to run scheme script in R7RS is csi -R r7rs, or csi (import (scheme base)) . No need csi -R r7rs and (import (scheme base)), and csi -R r7rs and (import (scheme base)) are the same thing.

@lassik
Copy link
Member

lassik commented Aug 16, 2021

Yes, csi -R r7rs -s foo.scm is the way to run an R7RS script using Chicken. However, portable R7RS scripts should also start with (import (scheme base)).

@lassik
Copy link
Member

lassik commented Aug 16, 2021

@lassik in Guile and Chicken there are no bytevector? is there a way to make the function works if the function is defined and not?

In R7RS, and many non-R7RS Scheme implementations as well, that can be done with cond-expand:

(import (scheme base) (scheme write))

(cond-expand
 (r7rs
  (define type-of-alist-extra (list (cons bytevector? 'bytevector))))
 (else
  (define type-of-alist-extra '())))

(define type-of-alist
  (append type-of-alist-extra
          (list (cons boolean?    'boolean)
                (cons char?       'character)
                (cons eof-object? 'eof-object)
                (cons null?       'null)
                (cons number?     'number)
                (cons pair?       'pair)
                (cons port?       'port)
                (cons procedure?  'procedure)
                (cons string?     'string)
                (cons symbol?     'symbol)
                (cons vector?     'vector))))

(define (type-of obj)
  (let loop ((alist type-of-alist))
    (and (not (null? alist))
         (if ((caar alist) obj) (cdar alist) (loop (cdr alist))))))

(define (writeln x) (write x) (newline))

(writeln (type-of 123))
(writeln (type-of "abc"))
(writeln (type-of #\x))
(writeln (type-of (lambda (x) x)))
(writeln (type-of 'abc))
(writeln (type-of #(1 2 3)))
(writeln (type-of '(1 2 3)))
(writeln (type-of '()))
(writeln (type-of (eof-object)))
(writeln (type-of (current-input-port)))
(writeln (type-of (bytevector 1 2 3)))

@jcubic
Copy link
Contributor Author

jcubic commented Aug 16, 2021

That is much better because you can extend the types easily, I wanted to create a dictionary with types but forget about Alist. I do too much JavaScript recently.

This was referenced Aug 18, 2021
@jcubic jcubic closed this as completed Aug 26, 2021
@APIPLM
Copy link

APIPLM commented Sep 26, 2021

@lassik As we talked in the above, the standard way to run the top level script in Chicken is that ./csi -R r7rs -s foo.scm. But check with the r7rs-tools egg, it export two symbols eval , environment for the environment to run the script. But actually it just one ,it is environment. So what is its usage? Should it be in r7rs standard environment when running the top level script?

@APIPLM
Copy link

APIPLM commented Sep 27, 2021

Sorry. r7rs egg just internally import scheme.eval, which have the symbols eval and environment. it does not export both symbols

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants