Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Nov 27 22:48
    feeley commented #800
  • Nov 27 22:29
    lassik commented #800
  • Nov 27 18:20
    amirouche commented #800
  • Nov 27 18:17
    amirouche opened #800
  • Nov 25 15:00
    CI run 3548417753 passed
  • Nov 25 13:58
    feeley commented on 8195d7d
  • Nov 25 13:39

    feeley on master

    Allow modules/libraries to be u… (compare)

  • Nov 21 10:40
    feeley commented #799
  • Nov 21 04:47
    FredericHamel commented #797
  • Nov 21 04:26
    FredericHamel edited #799
  • Nov 21 04:25
    FredericHamel opened #799
  • Nov 21 02:53
    FredericHamel commented #797
  • Nov 21 02:48
    FredericHamel ready_for_review #797
  • Nov 21 02:45
    FredericHamel synchronize #797
  • Nov 21 01:51
    feeley commented #797
  • Nov 21 01:44
    FredericHamel synchronize #797
  • Nov 17 21:40
    CI run 3491677909 passed
  • Nov 17 20:17
    CI run 3491150009 passed
  • Nov 17 20:16

    feeley on master

    Upgrade character data to Unico… (compare)

  • Nov 17 18:55

    feeley on master

    Remove old, unused code. Some … Merge pull request #798 from ga… (compare)

Marc Feeley
@feeley
> (define (a x y #!optional z) (list 'x= x 'y= y 'z= z))
> (define (b x y #!optional z #!rest rest) (list 'x= x 'y= y 'z= z 'rest= rest))
> (a 1 2)
(x= 1 y= 2 z= #f)
> (a 1 2 3)
(x= 1 y= 2 z= 3)
> (a 1 2 3 4)
*** ERROR IN (stdin)@5.1 -- Wrong number of arguments passed to procedure
(a 1 2 3 4)
1> ,t
> (b 1 2)
(x= 1 y= 2 z= #f rest= ())
> (b 1 2 3)
(x= 1 y= 2 z= 3 rest= ())
> (b 1 2 3 4)
(x= 1 y= 2 z= 3 rest= (4))
> (b 1 2 3 4 5)
(x= 1 y= 2 z= 3 rest= (4 5))
KM
@twoplustwo:matrix.org
[m]
oh yesm of course, I mixed it up ;)
cs7
@cs7:matrix.org
[m]
KM: "." is R5RS, #!rest #!optional #!key is DSSSL = some extension
KM
@twoplustwo:matrix.org
[m]
so there is no need for the extension when I only use rest. is there also a way to use keywords without dsssl ? lets say (define (h1 a #!rest r #!key k) (list a k r)) is this possible?
Marc Feeley
@feeley
> (define (foo x #!key y z . rest) (list 'x= x 'y= y 'z= z 'rest= rest))
> (foo 1)                                                               
(x= 1 y= #f z= #f rest= ())
> (foo 1 z: 2)
(x= 1 y= #f z= 2 rest= ())
> (foo 1 z: 2 y: 3)
(x= 1 y= 3 z= 2 rest= ())
> (foo 1 z: 2 y: 3 4)
(x= 1 y= 3 z= 2 rest= (4))
> (foo 1 z: 2 y: 3 4 5)
(x= 1 y= 3 z= 2 rest= (4 5))
KM
@twoplustwo:matrix.org
[m]
tried it in the repl, this is so cool
cs7
@cs7:matrix.org
[m]
KM: Stuff you learn (that wasn't obvious before you learned it), write it up on the wiki, someone else will probably has the same question later
cs7
@cs7:matrix.org
[m]
:point_up: Edit: KM: Stuff you learn (that wasn't obvious before you learned it), write it up on the wiki, someone else will probably have the same question later
KM
@twoplustwo:matrix.org
[m]
Is there a good way to replace strings in templates, like replace all {{key1}} {{key2}} with value1 valu2 in a string or maybe in a textfile?
Or if not, I could write my own, but how do I find a string position inside another one?
KM
@twoplustwo:matrix.org
[m]
I found this string-contains here https://practical-scheme.net/wiliki/schemexref.cgi?string-contains can I use it somehow?
Marc Feeley
@feeley
@twoplustwo:matrix.org This could be useful:
(define (string-substitute str delim proc-or-alist)

  (define (index-of c start)
    (let loop ((i start))
      (if (fx< i (string-length str))
          (if (char=? c (string-ref str i))
              i
              (loop (fx+ i 1)))
          i)))

  (let loop ((i 0) (j 0) (out '()))
    (let ((start (index-of delim j)))
      (if (fx< start (string-length str))
          (let ((end (index-of delim (fx+ start 1))))
            (if (fx< end (string-length str))
                (if (fx= start (fx- end 1)) ;; two delimiters in a row?
                    (loop (fx+ end 1)
                          (fx+ end 1)
                          (cons (substring str i end)
                                  out))
                    (let* ((var
                            (substring str (fx+ start 1) end))
                           (subst
                            (if (procedure? proc-or-alist)
                                (proc-or-alist var)
                                (let ((x (assoc var proc-or-alist)))
                                  (and x (cdr x))))))
                      (if subst
                          (loop (fx+ end 1)
                                (fx+ end 1)
                                (cons subst
                                        (cons (substring str i start)
                                                out)))
                          (error "Unbound substitution variable in" str))))
                (error "Unbalanced delimiter in" str)))
          (string-concatenate
           (reverse (cons (substring str i start) out)))))))

(pp (string-substitute "@a@ plus 1 is @b@" #\@ '(("a" ."two") ("b" . "three"))))
KM
@twoplustwo:matrix.org
[m]
cool, I will walk through this. how can I import string-concatenate ?
Marc Feeley
@feeley
@twoplustwo:matrix.org string-concatenate is builtin (you need v4.9.4)
cs7
@cs7:matrix.org
[m]
= same as string-append ?
Marc Feeley
@feeley
@twoplustwo:matrix.org (string-concatenate lst) = (apply string-append lst)
cs7
@cs7:matrix.org
[m]
ah yesyes i see. many thanks.
jeffhhk
@jeffhhk

Hello, I'm trying gambit for the first time, starting with the javascript support in 4.9.4. I am able to reproduce the instructions at

http://www.gambitscheme.org/latest/manual/#Compiling-Modules

However, if I change much from that basic scenario, stuff stops working. For example, here is my attempt to extend to importing SRFI 78:

git clone https://github.com/scheme-requests-for-implementation/srfi-78

cat srfi-78/srfi-78.sld
    (define-library (srfi-78)
      (import (scheme base))
      (export hello-world)
      (include "check.scm")
      (begin
        (define (hello-world)
          (display "hello world\n"))
    ))

cat hello-test/hello-test.sld
    (define-library (hello-test)
      (import (srfi-78) (scheme base) (scheme write))
      (begin
        (display
         (cond-expand
           ((compilation-target C)   "compiled to C\n")
           ((compilation-target (_)) "interpreted\n")
           (else                     "compiled to other\n")))
        (hello-world)
        (newline)))

gsc -target js . srfi-78 hello-test
    Building module: srfi-78

gsc -target js . srfi-78
    <no output>
gsc -target js . hello-test
    <no output>

gsc -target js -exe -nopreload . srfi-78/srfi-78.sld hello-test/hello-test.sld
    srfi-78/srfi-78.sld:
    /home/jeff/srchome/src/zipper/srfi-78/srfi-78.js:
    hello-test/hello-test.sld:
    /home/jeff/srchome/src/zipper/hello-test/hello-test.js:
    /home/jeff/srchome/src/zipper/hello-test/hello-test_.js:

hello-test/hello-test
    compiled to other
    *** ERROR IN hello-test# -- Operator is not a PROCEDURE
    (#!void "hello world\n")
I would have expected:
  • two "Building module" messages for building srfi-78 and hello-test together
  • one "Building module" message for building srfi-78 and hello-test each separately
  • successful -exe generation to result in a runnable program.
Results are the same with or without the (include "check.scm") commented out.
jeffhhk
@jeffhhk
Thanks in advance for any help!
jeffhhk
@jeffhhk
Well I figured out one thing:
(define-library (srfi-78)
  (import (scheme base) (scheme write))

Now:

gsc -target js . srfi-78 hello-test && \
gsc -target js -exe -nopreload . srfi-78/srfi-78.sld hello-test/hello-test.sld && \
node hello-test/hello-test

emits:

Building module: srfi-78
srfi-78/srfi-78.sld:
/home/jeff/srchome/src/zipper/srfi-78/srfi-78.js:
hello-test/hello-test.sld:
/home/jeff/srchome/src/zipper/hello-test/hello-test.js:
/home/jeff/srchome/src/zipper/hello-test/hello-test_.js:

compiled to other
hello world
jeffhhk
@jeffhhk

So that's good. Still can't get these:

(export hello-world check)
(include "check.scm")

To allow this:

(check (+ 2 2) => 4)
Ok, this did the trick:
(define-library (srfi-78)
  (import (scheme base) (scheme write))
  (export hello-world check check-passed? check-report check-reset! check-set-mode!
    check:add-correct! check:add-failed! check:correct check:failed
    check:mode check:proc check:proc-ec check:report-actual-result
    check:report-correct check:report-expression check:report-failed
    check:write)
  (include "check.scm")
  (begin
    (define (hello-world)
      (display "hello world\n"))
))
I think I've answered my question. Thanks!
Marc Feeley
@feeley
@jeffhhk Yes the macro dependencies are not automatically exported (as they should be implicitly)… this is being worked on
BTW the -warnings option to gsc is useful in this situation
jeffhhk
@jeffhhk
@feeley Good to know, thanks!
jeffhhk
@jeffhhk

I'm looking for a workflow to incrementally develop a library in the r7rs define-library style, including the ability to test in a repl. Currently using emacs scheme-mode for sending to the repl.

Suppose I want to change the library and then as quickly as possible test with the repl. I wrote a wrapper script to run gsi which finds the correct directory to pass with -:search so that my import will work. But after making a change I noticed when doing import as above in gsi that I can't seem to do import again and pick up the change. I'm okay with clearing out my environment to do so.

  • I tried finding a clear scheme environment api, but didn't see one.
  • I tried passing -prelude "(import (my-lib))" to get a gsc repl, but gsc doesn't evaluate display statements before dropping to the repl.
  • I tried passing -prelude "(import (my-lib))" to gsi, but gsi seems to reject it outright.

I suppose I could script this with a custom emacs command or subprocess tty hacks, but I was hoping to stay within gambit for editor independence. Is there any similar api available?

jeffhhk
@jeffhhk
Here's an attempt to use .gambini to do a project-specific repl initial import:
(display "hello $HOME/.gambini\n")

(define (dir-for-project)
  (let loop ((d (path-strip-trailing-directory-separator (current-directory))))
    (let ((files (directory-files (list (string->keyword "path") d (string->keyword "ignore-hidden") #f))))
      (if (or (equal? 0 (string-length d))
          (member ".gambini-local" files))
      d
      (loop (path-strip-trailing-directory-separator (path-directory d)))))))

(map display `(about to add ,(dir-for-project) "\n"))
(module-search-order-add! (dir-for-project))

;; TODO: look for project-specific modules to load in .gambini-local

;; For now, simulate by hard-coding:

;;(import (srfi-78))
;;  =>
;;  Cannot find library (srfi-78)
(eval "(define foo 123)")
;; does not cause error, but foo is not bound in the repl
Marc Feeley
@feeley
@jeffhhk you probably want:
$ gsi . -e "(import (srfi 28))" -
> (format "~a + ~a = ~a" 1 2 3)
"1 + 2 = 3"
and for eval you want: (eval ‘(define foo 123))
because (eval “a string”) => ”a string”
Marc Feeley
@feeley
This undocumented feature may also be useful:
$ gsi
Gambit v4.9.4-39-g9a887b80

> (import foo/bar) ;; same as (import (foo bar))
> (##remove-registered-module ‘foo/bar)
...
> (import foo/bar) ;; will load it again
jeffhhk
@jeffhhk
Great thanks! All useful. Here it is all put together:
#|
Initializes project-specific path and imports for repl-based testing.
Place initialization code for your gambit based project in the project
root directory.

For example:
    mkdir -p srfi-78
    git clone https://github.com/scheme-requests-for-implementation/srfi-78 srfi-78/srfi-78
    cat > srfi-78/srfi-78.sld 
        (define-library (srfi-78)
          (import (scheme base) (scheme write))
          (export hello-world check check-passed? check-report check-reset! check-set-mode!
            check:add-correct! check:add-failed! check:correct check:failed
            check:mode check:proc check:proc-ec check:report-actual-result
             check:report-correct check:report-expression check:report-failed
            check:write)
          (include "srfi-78/check.scm")
          (begin
            (define (hello-world)
              (display "hello world\n"))
        ))
    cat > .gambini-local
        (import (srfi-78))
        (define bar 456)
    gsi
        hello HOME/.gambini
        Found .gambini-local.  Will module-search-order add ../src/zipper
        About to eval: (begin (import (srfi-78)) (define bar 456))
        Gambit v4.9.4

        > bar
        456
        > (check (+ 2 2) => 4)

        (+ 2 2) => 4 ; correct
        >     
|#
(import (srfi 28))

(define rfile-local ".gambini-local")

(define (dir-for-project)
  (let loop ((d (path-strip-trailing-directory-separator (current-directory))))
    (let ((files (directory-files (list (string->keyword "path") d (string->keyword "ignore-hidden") #f))))
      (cond
       ((equal? 0 (string-length d)) #f)
       ((member rfile-local files) d)
       (else 
    (loop (path-strip-trailing-directory-separator (path-directory d))))))))

(define (file-for-project)
  (path-expand rfile-local (dir-for-project)))

(if (dir-for-project)
    (begin
      (display (format "Found .gambini-local.  Will module-search-order add ~a\n" (dir-for-project)))
      (module-search-order-add! (dir-for-project))

      (let ((sexp-local `(begin ,@(with-input-from-file ".gambini-local" (lambda () (read-all (current-input-port)))))))

    (display (format "About to eval: ~a\n" sexp-local))
    (eval sexp-local))))
jeffhhk
@jeffhhk

A curious thing about the above .gambini is that it runs even when initializing gsc for batch compilation. Is there an API for detecting running in a repl, such as cond-expand?

If not, I suppose I could guard the above with an environment variable and only set it in my testing repl.

Marc Feeley
@feeley

@jeffhhk The Gambit manual has this explanation:

Extensions which are meant to apply to a single user or to a specific working directory are best placed in the initialization file, which is a file containing Scheme code. In all modes, the interpreter first tries to locate the initialization file by searching the following locations: ‘.gambini’ and ‘ ̃/.gambini’ (with no extension, a ‘.sld’ extension, a ‘.scm’ extension, and a ‘.six’ extension in that order). The first file that is found is examined as though the expression (include initialization-file) had been entered at the read-eval-print loop where initialization-file is the file that was found. Note that by using an include the macros defined in the initialization file will be visible from the read-eval-print loop (this would not have been the case if load had been used). The initialization file is not searched for or examined when the ‘-f’ option is specified.

The .gambini file will be visited by gsi and gsc (unless the -f option is specified) because the code it contains is meant to configure or extend the Gambit runtime library. There are various ways to detect if code is being run by gsi or gsc:
1) check for presence of compile-file procedure which is defined only by gsc:

(if (##unbound? (##global-var-ref (##make-global-var 'compile-file)))
    (display “gsi\n”)
    (display “gsc\n”))

2) check the name of the executable:

(if (member (path-strip-directory (executable-path)) '("gsi" "gsi-script”))
    (display “gsi\n”)
    (display “gsc\n”))

3) if you want to check if code is interpreted or compiled:

$ cat .gambini
(define-macro (interpreted-code?)
  `(cond-expand ((compilation-target (_))
                 #t)
                (else
                 #f)))
$ cat foo.scm
(if (interpreted-code?)
    (display "interpreted code\n")
    (display "compiled code\n"))
$ gsi foo.scm
interpreted code
$ gsc -exe foo.scm
$ ./foo
compiled code
$ gsc -i foo.scm
interpreted code
$ gsc
Gambit v4.9.4-39-g9a887b80

> (load "foo.scm")
interpreted code
"/Users/feeley/foo.scm"
> (compile-file "foo.scm")
"/Users/feeley/foo.o1"
> (load "foo.o1")
compiled code
"/Users/feeley/foo.o1"

Note that with #3 it is not the program (gsi or gsc) that is checked, but rather the way the code is executed, which is often a more robust test because gsc can both compile and interpret code (when given the -i option or no command line arguments).

1 reply
Ricardo G. Herdt
@r.herdt_gitlab

Hi there!
While porting my json-rpc to Gambit, I found a possible bug:

> (alist->hash-table '())
*** ERROR IN (stdin)@2.1 -- PAIR LIST expected
(srfi/69#alist->hash-table '())

Trying to convert an empty list into a hash-table sounds lame, but I'm using it as a set-filter for make-parameter, like this:

(define json-rpc-handler-table
  (make-parameter '() (lambda (alist) (alist->hash-table alist equal?))))

I'm using v4.9.4. BTW, I also noticed that gsi still shows v4.9.3

Ricardo G. Herdt
@r.herdt_gitlab
another bug: define-values seems not to work inside a lambda/function definition. According to R7RS define-values "is allowed wherever define is allowed":
> (define (f) (define-values (a b) 1 2) #t)     
*** ERROR IN (stdin)@2.13 -- Unknown expression parsing exception
Marc Feeley
@feeley
The bug with SRFI 69 is kind of embarassing… now fixed and I have added unit tests for this.
Concerning the problem with define-values, the correct implementation of this form and other R7RS forms depends on the new macro system we are working on… in the meantime you can use this definition:
(define-macro (define-values vars expr)
  (cond ((null? vars)
         (let ((temp (gensym)))
           `(##define ,temp
              (##call-with-values (##lambda () ,expr) ##list))))
        ((null? (cdr vars))
         `(##define ,(car vars) ,expr))
        (else
         (let ((temp (gensym)))
           `(##begin
              (##define ,temp
                (##call-with-values (##lambda () ,expr) ##list))
              ,@(map (lambda (var)
                       `(##define ,var
                          (##if (##pair? ,temp)
                                (##let ((val (##car ,temp)))
                                  (##set! ,temp (##cdr ,temp))
                                  val)
                                (##error "too few values"))))
                     vars))))))
Ricardo G. Herdt
@r.herdt_gitlab
Thanks Marc!
Mark Friedman
@mark-friedman

In the "try" IDE, I'd like to change the orientation of the console and editor panes from horizontal to vertical, i.e. have the console on top of the editor. I thought that maybe just changing UI.js:59 from:

  elem.classList.add('g-h-panes');

to

  elem.classList.add('g-v-panes');

might suffice, but no such luck. I end up just seeing the console. Most all of the class/style stuff seems to be nicely abstracted but I'm guessing that there is an assumption built somewhere in there (maybe the CSS) that is breaking it. Any guidance would be appreciated. My CSS-fu is not strong.

Thanks.

Mark Friedman
@mark-friedman

Another question about the web-based IDE in contrib/try: Do I really need to server all the files in the try\try\lib directory? I assume that some or all of it is to support a set of auto-loaded modules, some or all of which are needed by the demo code. Are any of them needed for core R7RS-small execution? Also, are all the various file types in a given subdirectory necessary? Typically I will see foo.scm, foo.js, foo#.scm, foo.o1, foo.o1.js, and foo.o1.js.gzfiles.

I'm fairly new to Gambit (though not to Scheme), so forgive my naiveté ;-)

Marc Feeley
@feeley
@mark-friedman Sorry but my CSS-fu is not that strong either. As I recall, CodeMirror causes a lot of headaches to do resizing correctly. I did notice however that the pane-splitter is actually dragable close to the top of the REPL and you can drag it down to reveal the console. I hope someone with a PhD in CSS can sort out this issue...
1 reply
tck42
@tck42
Is there any way to override the default CFLAGS etc that gsc issues at runtime during build without changing the flags that are used to compile? The bleeding edge Fedora build is using custom linker scripts that are fine for gambit itself but they reference a linker script that's only available on the build server. I'd like to open the bug with a suggested working build. I checked the build docs but it's not clear to me which options end up where.
Mark Friedman
@mark-friedman
Thanks, @feeley for your answer about the orientation of the console and editor panes in "try". Do you (or anybody else) have an answer for my subsequent "try"-related question relating to all the different files and files types?
Konstantin Astafurov
@konstantin-aa
Hello, I'm writing some scheme that involves parsing JSON, and am having a bit of trouble with using the json.scm from here
Marc Feeley
@feeley
@mark-friedman None of the try/lib files are essential… they are there for dynamic loading of various standard modules… if you use the R7RS define-library then you will need try/lib/_define-library
8 replies