How do I serialize an object into JSON including defined variables in Racket? - json

I am trying to to write a json structure to a file using racket. The actual function for writing works fine but when creating the data structure which I write to the file, I simply cannot figure out how to include values from bound variables.
(start_location . "h")
(end_location . "t")
(ETA . 30)
(route . ("g"))
(optional_parameters . #hasheq((accessibility . #f)))
))
(define write-json-wrapper (lambda (jsexpr filename)
(call-with-output-file filename (lambda (x) (write-json jsexpr x)) #:exists 'replace)
))
The above structure works when I write it to the file.
(define x "h")
(define b #hasheq(
(start_location . x)
(end_location . "t")
(ETA . 30)
(route . ("g"))
(optional_parameters . #hasheq((accessibility . #f)))
))```
However when I try to use the value stored in x as the value for start_location it throws an error.
write-json: expected argument of type <legal JSON value>; given: 'x
Any help or explanation would be much appreciated.

#hasheq is literal for hash table and its content isn't evaluated:
#hasheq((a . 5) (b . 7)) reads equal to (make-...eq '((b . 7) (a . 5)))
If you want to use values of variables, you have to use make-hasheq like this:
#lang racket
(require json)
(define x 1)
(define y 2)
(define z 3)
(define jsexpr
(make-hasheq (list (cons 'x x)
(cons 'y y)
(cons 'z z))))
(define write-json-wrapper (lambda (jsexpr filename)
(call-with-output-file filename
(lambda (x) (write-json jsexpr x)) #:exists 'replace)))
Example:
(write-json-wrapper jsexpr "foo.txt")
If you're familiar with quasiquote, you can do also this:
(define jsexpr
(make-hasheq `((x . ,x)
(y . ,y)
(z . ,z))))
So for your data:
(make-hasheq `((start_location . ,x)
(end_location . "t")
(ETA . 30)
(route . ("g"))
(optional_parameters . #hasheq((accessibility . #f)))))

Related

Redefining a fuction used to define this function in Scheme

I think the title is a bit weird but, for example, is there a way to redefine the addition in Scheme so that (+ arg1 arg2) gives arg1 + arg2 + 1?
I can create a new function #:
(define # (lambda args (+ (apply + args) 1)))
such that (# 42 13) gives (42 + 13 + 1). But is there a way to do something which would look like:
(define + (lambda args (+ (apply + args) 1)))
but of course without the error since, here, it says that + is undefined?
In R7RS version of Scheme we have imports so here we can do it:
#!r7rs
(import (except (scheme base) +)
(rename (scheme base) (+ base:+)))
(define (+ . args)
(apply base:+ 1 args))
(+ 1 1) ; ==> 3
In R6RS version its the same except (scheme base) is (rnrs base)
Racket has something very similar:
#lang racket
(require (only-in racket/base [+ base:+]))
(define (+ . args)
(apply base:+ 1 args))
(+ 1 1) ; ==> 3
In R5RS report Scheme and older the report allows a user to redefine a procedure to extend the features of it, but it is a violation that it for the defined types would result in different results than the original scheme report version would. Thus redefining + like this is a violation and not portable Scheme. It might work in some implementation, but the wording is done such that a smart Scheme compiler can do constant folding and expect the correct result from supported types.
#!r5rs
(define +
(let ((r5rs:+ +))
(lambda args
(apply r5rs:+ 1 args))))
(+ 1 1) ; ==> 2 or 3, perhaps an error

Make Scheme function for 3 parameters return function for the 3d

I'm having a hard time converting this rather simple Scheme function, into a function that returns another function taking in a list and applying the former function to all elements on that list.
This function
(define (operList op i lis)
(if (= 0 (length lis)) '()
(cons (op i (car lis)) (operList op i (cdr lis))))
)
Can be called like this
(operList + 2 '(1 1 1))
and returns '(3 3 3)
However, how can I edit this function so that I can call it in the following manner
((operList + 2) '(1 1 1))
with the same results
You have to return a new function that receives the list. I took the liberty of fixing the indentation and the base case (that's not how you should ask if a list if empty!); pay special attention to the way the recursion is called now:
(define (operList op i)
(lambda (lis)
(if (null? lis)
'()
(cons (op i (car lis))
((operList op i) (cdr lis))))))
It works as expected:
((operList + 2) '(1 1 1))
=> '(3 3 3)
You could also use map:
(define operList
(lambda (op i)
(lambda (lst)
(map
(lambda (x) (op i x))
lst))))

Can a function return a function that isn't a lambda?

Everytime I see functions returning functions, the returned function is always a lambda. I'm wondering if I can have my function return a function that has a name to it.
The syntax that you are trying to use is correct, simply use the name of the inner function as value returned by the outer function. For instance you can write:
(define (incrementer x)
(define (adder y)
(+ x y))
adder)
(define incrementer-by-1 (incrementer 1))
(define incrementer-by-2 (incrementer 2))
(incrementer-by-1 3)
(incrementer-by-1 10)
(incrementer-by-2 15)
As a comment says, keeping in mind that (define (f x) y) is just an abbreviation for (define f (lambda(x) y)), the previous function is equivalent to:
(define (incrementer x)
(lambda (y)
(+ x y)))
As another example, you can return a function which was previously defined:
(define (make-positive x)
(abs x))
(define (make-negative x)
(- (abs x)))
(define (same-signer x)
(if (>= x 0)
make-positive
make-negative))
((same-signer 3) -2)
Here is a small example.
#lang racket
(define (fun1) "Function 1")
(define (fun2) "Function 2")
(define (number->function n)
(cond
[(= n 1) fun1]
[(= n 2) fun2]
[else (error 'number->function "expected 0 or 1 as input")]))
(number->function 1)
((number->function 1))
The output is:
#<procedure:fun1>
"Function 1"

Isearch return t if found for loop function in Emacs Lisp

How to write a function where whenever a variable is found, it returns t (in order to allow a loop):
(setq x 1)
(while ("backward search for regexp "%x" equals true") ;where x is variable
(setq x (+ x 1))
(insert (concat "%" (int-to-string x)))
)
Example: If %1 (x=1) is found, it will add 1 to x. If %2 (x=2) is found, it will add 1 to x.
Let's say %3 is not found in a backward search, the while loop stops and "%" + "3" is inserted (%3).
I just don't understand the how to return true on a backward-search.
search-backward takes an optional third argument which, when non-nil, tells it to return nil in case the search was unsuccessful:
(setq x 1)
(while (search-backward (format "%%%d" x) nil t)
(setq x (1+ x)))
(insert (format "%%%d" x))
Now, if I try to understand what you really want to do (something like inserting at point the first %d string which doesn't appear before), then you might want to wrap the search inside a save-excursion form to avoid moving the point:
(setq x 1)
(while (save-excursion (search-backward (format "%%%d" x) nil t))
(setq x (1+ x)))
(insert (format "%%%d" x))
With help from Francesco
(defun Navi-insert-question ()
(interactive)
(setq x 1)
(while (save-excursion
(search-backward (concat comment-start " Question: " (int-to-string x)) nil t))
(setq x (+ 1 x)))
(insert (concat comment-start " Question: " (int-to-string x))))
It now results in being able to insert in R, for instance: "# Question: 1", when it exists above in the buffer it will insert "# Question: 2".

How do you define a variadic function in a Chicken Scheme module?

Is this a bug in Chicken Scheme?
#;1> (define (foo x . y) x)
#;2> (foo 1 2 3)
1
#;3> (module bar (import scheme chicken) (define (foo x . y) x))
Error: invalid syntax in macro form: (foo x . y)
Call history:
<syntax> (module bar (import scheme chicken) (define (foo x . y) x))
<syntax> (##core#module bar (import scheme chicken) (define (foo x . y) x))
<syntax> (define (foo x . y) x)
<syntax> (foo x . y) <--
Your module syntax is missing the list of symbols to export from the module. Try this:
#1;> (module bar (foo) (import scheme chicken) (define (foo x . y) x))
#2;> (import bar)
#3;> (foo 1 2 3)
1
Notice the (foo) after declaring the module name.
I'll add that the mailing list and irc channel (#chicken on freenode) are very active. If you have questions about chicken they are the best places to get them answered.
The dot (.) syntax for variadic functions is not available across modules; it's inside the scheme module. When you create a custom module, you have to explicitly import the scheme module to reenable variadic functions.
#1;> (module bar (foo) (import scheme chicken) (define (foo x . y) x))
#2;> (import bar)
#3;> (foo 1 2 3)
1