LISP clause for and clause let ¿why?,making a programming language in racket using ragg - scheme

I have long been trying to find the error, I'm doing a programming language and have the next code, using ragg, I have a syntax-object(resto ...) what has a bracket as data, I transform this syntax-object to a datum:
(let ([i (syntax->datum #'(resto ...))])
(display "Content i:")
(display i)
(if (eq? i (string->symbol "(})"))
(display "true")
(display "false")
)
)
and the output is:
Content: (})
false
But if I do this
(for ([i (syntax->datum #'(resto ...))])
(displayln "Content:")
(displayln i)
(if (eq? i (string->symbol "}"))
(display "true")
(display "false")
)
)
and the output is:
Content: }
true
MY QUESTION:
¿WHY THE IF OF CLAUSE LET IS FALSE?
¿AS I CAN COMPARE THESE TWO TYPES AND THAT THE RESULT IS TRUE WITHOUT THE FOR?
Documentation about functions:
syntax->datum

Each piece of code is doing a very different thing, I'll show you how to make each one work. The first one uses let to assign into a variable the whole list returned by syntax->datum, and afterwards you compare it against another list (better use equal? for testing equality, it's more general):
(let ([i (syntax->datum #'(|}|))]) ; `i` contains `(})`
(display "Content i: ")
(displayln i)
(if (equal? i '(|}|)) ; a list with a single element, the symbol `}`
(displayln "true")
(displayln "false")))
The second piece of code is using for to iterate over each element in a list, until it finds the symbol }:
(for ([i (syntax->datum #'(|}|))]) ; `i` contains `}`
(display "Content i: ")
(displayln i)
(if (equal? i '|}|) ; the symbol `}`
(displayln "true")
(displayln "false")))
As a side note, you have to be very careful with the way you're going to process all those curly brackets {} in your language, they're interpreted as normal parentheses () in Racket and they'll be tricky to handle, notice how I had to escape them by surrounding them with vertical bars.

Related

How to parse a function into another function in scheme

I am trying to create a function that takes another function as a parameter and calls the functions in a loop.
The code below should get the function and the number of times the loop should execute:
(define (forLoop loopBody reps)
(let
(
(fun (car loopBody))
(str (cdr loopBody))
)
(cond
((eval (= reps 0) (interaction-environment)) "")
(else (cons str (forLoop '(fun str) (- reps 1))))
)
)
)
The code below is how i am calling the function
(define (printermsg)
(display msg)
)
(forLoop '(printer "text ") 4)
The expected output for the above code:
text text text text
There are several issues with your code:
The way you pass the loopBody parameter to your function is incorrect, a list of symbols will not work: you want to pass along a list with the actual function and its argument.
You are not obtaining the second element in the list, cdr won't work because it returns the rest of the list, you need to use cadr instead.
Avoid using eval, it's not necessary at all for what you want, and in general is a bad idea.
Why are you building a list? cons is not required here.
When calling the recursion, you are again passing a list of symbols instead of the proper argument.
You're not actually calling the function!
This should work:
(define (forLoop loopBody reps)
(let ((fun (car loopBody))
(str (cadr loopBody)))
(cond
((= reps 0) (void)) ; don't do anything when the loop is done
(else
(fun str) ; actually call the function!
(forLoop loopBody (- reps 1))))))
(define (printer msg)
(display msg))
(forLoop (list printer "text ") 4) ; see how to build the loop body
=> text text text text

User input to a list

I'm trying to take in user input and add it to a list but I have not been able to get it working. I'm still new to scheme and have been browsing around to try to figure it out but I haven't had any luck.
(display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(define (intlist number)
(define number(read-line))
(cond (number? number)
(cons lst (number))
(else
(display lst)
done')))
this is what I have so far. Any help or direction to where I can learn a bit more is appreciated.
Your solution is almost correct, but it doesn't work, because:
Variable lst doesn't exist and with this expression (number), you are calling some undefined function number.
done' is badly written 'done.
Function cons expects element as first argument and other element or list as second argument.
See these examples:
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
> (cons 1 (cons 2 (cons 3 '())))
'(1 2 3)
Last example is important here- your function will be recursive and it will return a cons cell in each step. If I will follow your solution, this can be enough:
(define (list-from-user)
(let ((number (read)))
(if (number? number)
(cons number (list-from-user))
'())))
(Note that I used read instead of read-line, because read-line returns string, and let instead of define.)
If you really want to wait for e, you must decide, what happens if user enters something that isn't number and isn't e- maybe just ignore it?
(define (list-from-user)
(let ((user-input (read)))
(cond ((number? user-input) (cons user-input (list-from-user)))
((eq? user-input 'e) '())
(else (list-from-user)))))
Then just add some wrapping function with output:
(define (my-fn)
(begin (display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(list-from-user)))
and call it
> (my-fn)
Note that my function returns list with numbers, instead of some useless 'done, so I can use that function in other functions.
(define (sum-of-list)
(let ((lst (my-fn)))
(format "Sum of given list is ~a." (apply + lst))))
> (sum-of-list)

How to write to stdout within a conditional expression in MIT-Scheme?

Here is an example of an attempt to write a different string to stdout depending on the value of a variable:
(let ((x 1))
(cond ((< x 2)
(display "hooray"))
(else
(display "bummer")))
)
Notice that the correct string does get written, but we also get an "Unspecified return value"
My understanding is that this happens because the interpreter is trying to return the value of the "consequent expression" of the clause as the value of the conditional, but the "display" expression does not return any value.
Is there a better way of doing this?
Given that this expression is evaluated only for its effect (printing a message), you should explicitly return a value (any value!) as the result of the let form:
(let ((x 1))
(cond ((< x 2)
(display "hooray")
(newline))
(else
(display "bummer")
(newline)))
'ok)
Now we'll get:
hooray
'ok

Getting #<undef> back when calling a scheme function

I have the following code in Scheme:
(define (processExpression lst)
(define operand (car lst))
(define operator1 (cadr lst))
(define operator2 (caddr lst))
(if (list? operand)
(begin
(display "Invalid syntax! Erroring out!")
(quit)
)
)
(if (and (number? operator1) (number? operator2))
;The list was of the form (operand c1 c2)
(simplePrefix lst)
)
(if (and (list? operator1) (number? operator2))
(begin
(list operand operator2 (processExpression operator1))
)
)
)
(define (simplePrefix lst)
(let (
(operand (car lst))
(operator1 (cadr lst))
(operator2 (caddr lst)))
(list operator1 operand operator2)
)
)
(display "Please enter a valid s-expression")
(let ((input (read)))
(display (simplePrefix input))
)
This code takes and s-expression and converts it based on some rules. One rule should be that the expression (+ (+ 1 2) 2) should return (+ 2 (1 + 2)).
Currently when I call this code with that expression I get back the result "#undef>" but I have no idea why. The code should call the simplePrefix function on the (+ 1 2) part of the expression and return (1 + 2) but it does not. Does anyone understand why?
The value of
(if condition
something)
is undefined if condition is false, because there's no else part in the if form. In the R5RS version of Scheme, this is stated (emphasis added):
4.1.5 Conditionals
syntax: (if <test> <consequent> <alternate>)
syntax: (if <test> <consequent>)
Syntax: <Test>, <consequent>, and <alternate> may be arbitrary expressions.
Semantics: An if expression is evaluated as follows: first, <test> is evaluated. If it yields a true value (see section
6.3.1), then <consequent> is evaluated and its value(s) is(are) returned. Otherwise <alternate> is evaluated and its value(s)
is(are) returned. If <test> yields a false value and no
<alternate> is specified, then the result of the expression is
unspecified.
(if (> 3 2) 'yes 'no) ===> yes
(if (> 2 3) 'yes 'no) ===> no
(if (> 3 2)
(- 3 2)
(+ 3 2)) ===> 1
Some Scheme-like languages (e.g., Racket) will actually warn you if you try this:
Welcome to Racket v6.1.
> (if #t
(display "hello"))
stdin::1: if: missing an "else" expression
in: (if #t (display "hello"))
context...:
In Common Lisp, the else part is optional, and defined to be nil if not provided:
This is SBCL 1.2.4.58-96f645d, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
* (if t
(print 'hello))
HELLO
HELLO
* (if nil
(print 'hello))
NIL
The expression
(if condition result)
is not equivalent to
if condition
return result
in other languages.
It doesn't return a value, it has a value.
If the condition is false, that value is undefined.
If it is followed by other expressions in a sequence, the value is ignored and the following expressions are evaluated.
The result of evaluating a function application is the value of the last expression in the function's body
(define (foo)
(if (= 1 1)
"one is one")
"I am still here")
> (foo)
"I am still here"
These two added together lead to the error you're experiencing.

Binding function name as argument inside of macro

So I'm playing around with a simple doc-string system as a warmup in scheme, the idea being you could do something like:
(def-with-doc (foo a b)
(desc "Takes two parameters and sums them")
(param 'a "First parameter")
(param 'b "Second parameter")
(return "Sum of arguments")
(+ a b)
Which would be turned into:
(begin
(begin
(desc 'foo "Takes two parameters and sums them")
(param 'foo 'a "First parameter")
(param 'foo 'b "Second parameter")
(return 'foo "Sum of arguments"))
(begin
(define (foo a b)
(+ a b))))
The macro I've written:
(define doc-symbol-list '(param desc return))
(define-macro (def-with-doc arg-list #!rest body)
;; Loop over body, splitting into doc calls and everything else
(let loop ((remaining body) (docs '()) (main '()))
(if (null? remaining)
; Reverse accumulation order of docs and main
; And build re-ordered begin tree
(let ((docs (cons 'begin (reverse docs)))
(main (cons 'begin (reverse main))))
(cons 'begin `(,docs ,`(define ,arg-list ,main))))
; Accumulate into docs list if expression is reserved
; Otherwise into the body list
(let ((sexp (car remaining)) (rest (cdr remaining)))
(if (member (car sexp) doc-symbol-list)
(loop rest (cons sexp docs) main)
(loop rest docs (cons sexp main)))))))
Takes the definition, moves the param/desc/return calls into the top level wrapped in begin statements and reconstructs the body of the function, that way the doc string calls are only executed once when the file is loaded rather than each time the function is called. I know I could manually put the doc-string stuff at the top level but I'm trying to emulate Python doc-strings.
Anyhow, the last think that I need to do is bind the function name (foo in above) into the doc-string calls, so that (param 'a "First parameter") becomes (param 'foo 'a "First parameter") so that the function each call is associated with is known. This is where I'm having trouble, every attempt I've made has failed to do what I want.
I would suggest using define-syntax as it is hygienic and its syntax-rules are pretty easy to understand. syntax-rules are in a pattern-to-result format; if you can understand cond, you can understand syntax-rules.
I think this does what you want, judging by the before and after snippets.
(define-syntax def-with-doc
(syntax-rules ()
;; this pattern
[(_ (func params ...)
(tag attributes ...)
...
code)
;; is converted into
(begin
(tag (quote func) attributes ...)
...
(define (func params ...)
code))]))
Forgive my terminology because I've never used doc-strings.
Basically, this matches against anything that follows that pattern of a function + params def, 0 or more tags with attributes, and a code statement.
Then, it just rearranges everything.

Resources