Chicken Scheme: Does module procedures only use procedures internal to the module? - module

Assume I have the following two modules:
(module mod1 (func2)
(define (func1) ...)
(define (func2) ... (func1) ...))
(module mod2 ()
(import (only mod1 func2))
(define (func1) ...)
(define (func3) ... (func2) ...))
Does the call to func2 in func3 use mod2's version of func1 or mod1's version?

The best way to do this is to pass func1 to func2 somehow. Either as an argument, or through a SRFI-39 parameter that mod1 exports:
(module mod1 (func2)
(define (func1) ...)
(define the-func (make-parameter func1)) ; defaults to our version
(define (func2) ... (let ((func1 (the-func)) (func1)) ...))
(module mod2 ()
(import (only mod1 func2))
(define (func1) ...)
(define (func3) ... (parameterize ((the-func func1)) (func2)) ...))

Related

Processing SQL Queries as Lazy Streams in Racket

Language: Racket (with SQL query code/pointer)
Libraries: db, racket/stream, racket/sequence
Goal: lazily process the value of sql queries using streams in Racket.
Question 1: how do you manipulate SQL query stream objects in Racket? (I can get the stream-first value of the stream but not the rest of the stream!)
#lang racket/base
(require db
racket/sequence
racket/stream)
(define db_sql_local
(mysql-connect
#:user "<my-username>"
#:database "<my-database>"
#:server "<my-server>"
#:port <my-port>
#:password "<my-password>"))
;; PROBLEM 1 HERE
(define test-stream
(sequence->stream
(in-query
chembl_sql_local
"SELECT * FROM <table-name>"
#:fetch +inf.0)))
(stream-first test-stream)
;; stream-first of test-stream returns the first-row of the table as a '(#vector).
Any advice or comments would be greatly appreciated - Thank you!
First, the sequence returned by in-query does not contain vectors; each "element" of the sequence contains multiple values, one per column returned. See the paragraph in the Sequence docs starting "Individual elements of a sequence..." about multiple-valued elements.
Second, using #:fetch +inf.0 (the default behavior) means that all rows are fetched before the sequence is returned. So there's nothing lazy about the code above; you could use query-rows instead and get a list, which would be easier to work with (and query-rows does represent each row as a vector).
Finally, use stream-rest to get the rest of a stream. For example:
(require db racket/stream racket/sequence)
(define c (sqlite3-connect #:database 'memory))
(define qseq (in-query c "SELECT 1, 2 UNION SELECT 3, 4" #:fetch 1))
qseq
;; => #<sequence>
(define qstream (sequence->stream qseq))
qstream
;; => #<stream>
(stream-first qstream)
;; => 1 2
(stream-rest qstream)
;; => #<stream>
(stream-first (stream-rest qstream))
;; => 3 4
thanks for your quick reply. The #:fetch 1 arg was definitely what I was looking for to make it lazy. I've attached updated code that should lazily stream sql queries to export tsv files.
(define sql_server
(mysql-connect
#:user <username>
#:database <db-name>
#:server <server>
#:port <port-num>
#:password <password>))
(define query-->stream
(lambda (db-conn query)
(sequence->stream
(in-query
db-conn
query
#:fetch 1))))
(define print-table-row-to-tsv
(lambda (ls port)
(cond
((null? ls)
(fprintf port "~c" #\newline)
(void))
((sql-null? (car ls))
(fprintf port "~a~c" "NULL" #\tab)
(print-table-row-to-tsv (cdr ls) port))
((null? (cdr ls))
(fprintf port "~a" (car ls))
(print-table-row-to-tsv (cdr ls) port))
(else
(fprintf port "~a~c" (car ls) #\tab)
(print-table-row-to-tsv (cdr ls) port)))))
(define get-table-col-names
(lambda (db-conn tbl-name)
(map (lambda (x) (vector-ref x 0))
(query-rows db-conn (string-append "DESCRIBE " tbl-name)))))
(define export-query-result-to-tsv
(lambda (db-conn tbl-name query)
(let* ((tbl-col-names (get-table-col-names db-conn tbl-name))
(output-file (open-output-file (format "~achembl_~a_table.tsv" (find-system-path 'home-dir) tbl-name) #:exists 'replace))
(stream (query-->stream db-conn query)))
(begin
(print-table-row-to-tsv tbl-col-names output-file)
(process-stream-to-tsv stream output-file)
(close-output-port output-file)))))
(define process-stream-to-tsv
(lambda (stream port)
(cond
((stream-empty? stream)
(void))
(else
(begin
(print-table-row-to-tsv (call-with-values (lambda () (stream-first stream)) list) port)
(process-stream-to-tsv (stream-rest stream) port))))))
(export-query-result-to-tsv sql_server "<table-name>" "SELECT * FROM <table-name>;")

'Symbol's value as variable is void:' when using parameter on defun inside lambda

I would like to make this function to set keybind more shorter.
(defun defkey-arg2 ()
(exwm-input-set-key (kbd "s-g")
(lambda ()
(interactive)
(start-process-shell-command gkamus nil gkamus))))
then I write the shorter function with 2 parameters (the keybind and the app name)
(defun defkey-arg2 (key command) (...)
When I try the key as parameter, it will work
(defun defkey-arg2 (key)
(exwm-input-set-key (kbd key)
(lambda ()
(interactive)
(start-process-shell-command gkamus nil gkamus))))
(defkey-arg2 "s-g")
But, when I try write function like this
(defun defkey-arg2 (key command)
or
(defun defkey-arg2 (command)
(exwm-input-set-key (kbd "s-g")
(lambda ()
(interactive)
(start-process-shell-command command nil command)))
(defkey-arg2 "gkamus")
it raises error:
Symbol's value as variable is void:' when using parameter on defun
The body of lambda isn't evaluated. Using a backquote, the value of command can be substituted into the resulting expression.
(defun defkey-arg2 (command)
(define-key (current-local-map)
(kbd "s-g")
`(lambda ()
(interactive)
(start-process-shell-command ,command nil ,command))))

How to obtain namespace of a custom lang in Racket?

I'm implementing a custom language in Racket in which I would like to provide an eval procedure bound to the namespace of this custom language.
my-lang.rkt:
#lang racket
(provide #%module-begin #%top #%datum #%app)
(provide quote)
(provide (rename-out [a b] [my-eval eval]))
(define-namespace-anchor anchor)
(define ns (namespace-anchor->namespace anchor)) ; wrong namespace
(define (my-eval x) (eval x ns))
(define a 1)
test.rkt:
#lang s-exp "my-lang.rkt"
(eval 'a)
(eval 'b)
As implemented, since ns is the namespace of my-lang.rkt, (eval 'a) evaluates to 1 while (eval 'b) fails.
I would like ns to be bound to the namespace of test.rkt so that (eval 'a) fails and (eval 'b) returns 1.
How should I define ns?
Here's a way using parameter and macro. There might be a better way:
;; my-lang.rkt
#lang racket
(provide #%top #%datum #%app (rename-out [##%module-begin #%module-begin])
quote
(rename-out [a b] [my-eval eval]))
(require syntax/parse/define
racket/splicing)
(define current-ns (make-parameter #f))
(define-syntax-parser ##%module-begin
[(_ . xs)
#'(#%module-begin
(define-namespace-anchor anchor)
(splicing-parameterize ([current-ns (namespace-anchor->namespace anchor)])
. xs))])
(define (my-eval x) (eval x (current-ns)))
(define a 1)
;; test.rkt
#lang s-exp "my-lang.rkt"
(eval 'b) ;=> 1
(eval 'a)
;; a: undefined;
;; cannot reference an identifier before its definition

Scheme - using `this` as argument of a lambda function?

Could someone please clarify the concepts behind this use of the "this" keyword?
(define call
(lambda (obj method-name . args)
(apply (obj method-name) obj args)))
(define -cuboid-
(lambda (w l h)
(define volume
(lambda (this)
(* h (call this 'area))))
(define area
(lambda (this)
(* w l)))
(lambda (method-name)
(cond
((eq? 'volume method-name) volume)
((eq? 'area method-name) area)
(else (error "method not found: ~s" method-name))))
(define r1 (-cuboid- 2 3 4))
(call r1 'area) ;=> 6
(call r1 'volume) ;=> 24
I understand that this is a keyword to refer to the object that is being used. I found out that this alone doesn't have any particular meaning in this program (it needs to refer to the arguments of the lambda functions).
The call is ((-cuboid- 2 3 4) 'volume), which brings to (* h (call this 'area)), where has this been defined?
this is simply the argument of the lambda, this could be anything; try changing it to, e.g., myself in the first lambda and me in the second (where it is not used, by the way, but needs to be there for the call to work).
The call to ((-cuboid- 2 3 4) 'volume) returns that procedure, with names bound according to the sketch below:
In call, r1 'volume calls the "lookup method" of -cuboid- and returns the volume procedure, which is then called with the obj argument, binding that to the name this
Thus, this gets bound to the r1 argument to call

Common Lisp unbound variable / defmacro

I need to make the function defmacro for my meta-circular interpreter that can read this syntax:
pseudoscheme> (defmacro (minus x y) (list ‘- y x))
MINUS
pseudoscheme> (expand-macro '(minus 3 2))
(- 3 2)
When I use this:
(defmacro my-defmacro ((name &rest args) &body body)
(let ((form (gensym))(env (gensym)))
(progn
`(setf (macro-function ',name)
(lambda (,form ,env))
(destructuring-bind ,args (rest, form) ,#body))
name
)
)
)
and then:
(my-defmacro (min a b)(list '- a b))
I get this error:
Error: The variable MIN is unbound.
I can't understand why.
-----EDITED-----
If I use this:
(defmacro my-defmacro ((name &rest args) &body body)
(let ((form (gensym))(env (gensym)))
`(progn (setf (macro-function ',name)
(lambda (,form ,env))
(destructuring-bind ,args (rest, form) ,#body))
',name)
)
)
and then:
(my-defmacro (min a b)(list '- a b))
I get this error:
Error: Odd number of args to SETF: ((MACRO-FUNCTION (QUOTE PLUS)) (LAMBDA (#:G786 #:G787)) (DESTRUCTURING-BIND (A B) (REST #:G786) (LIST # A B)))
Your my-defmacro works for you host CL system, but I get the feeling you want macro capabilities in your interpreter and this won't do it. (except if ythe interpreter environment is the global host implementations environment, but that would make a lot of challenges)
I don't know how you do compound procedures in your evaluator but when my evaluator gets a (lambda (x) (+ x x)) it is turned into (compound-procedure <env> (x) (+ x x)). My macros turn into almost the same except the first element is compound-syntax.
Every evaluated operator has a tag which tells it what it is (one of primitive-syntax, primitive-procedure, compound-syntax, compound-procedure) and I only need a general way of dealing with those 4.
The real difference between a compound procedure and compound syntax is that the arguments gets evaluated for a procedure and in a compound syntax the result gets evaluated.
So. Have you implemented so that ((lambda (x) (+ x x)) 5) works? Well, then you'll almost implemented macros as well. This is of course not true for a compiler, since this approach would expand the code every time it's run instead of expanding once when the closure gets created. (Optimizations is no way to go on the first version anyway)
For your 'edited code' you have a misplaced paren:
(defmacro my-defmacro ((name &rest args) &body body)
(let ((form (gensym))(env (gensym)))
`(progn (setf (macro-function ',name)
(lambda (,form ,env)) ;; <== HERE
(destructuring-bind ,args (rest, form) ,#body))
',name)
)
)
which leads to setf having three subforms. Rewrite it like this (while using standard Lisp formatting):
(defmacro my-defmacro ((name &rest args) &body body)
(let ((form (gensym))
(env (gensym)))
`(progn (setf (macro-function ',name)
(lambda (,form ,env)
(destructuring-bind ,args (rest, form)
,#body)))
',name)))