scheme functions - string

I have defined is-string?:
(define (is-string? expr)
(string? expr))
and also interpret-string:
(define (interpret-string expr env)
expr)
These are the functions I have written:
(define (string-equals? expr)
(and
(list? expr)
(= 3 (length expr))
(equal? '= (first expr))))
(define (interpret-string expr env)
(=
(internet (second expr) env)
(interpret (third expr) env)))
This is the interpreter for string:
((is-string? expr) (interpret-string expr env))
When I enter this line to check whether it works:
(check-expect (is-string-equals? ’(string-equals "abc" "abc"))
#t)
I get an error saying:
check-expect encountered the following error instead of the expected value, #t.
:: reference to undefined identifier: is-string-equals?
What would I have to do for is-string-equals? I have no clue.
here is the actual question asked as requested.
Extend the interpreter with a “string” datatype. You will need to write functions:
is-string?
interpret-string
and modify the interpret function to support the string datatype.
Also add two functions to work with strings within the interpreted language:
string-equals? to check if two given strings are the same.
string-join to return a new string formed by joining two strings togeter.
Make sure your functions pass the following tests:
(check-expect (is-string-equals? ’(string-equals "abc" "abc"))
#t)
(check-expect (interpret-string-equals ’(string-equals "abc" "abc") (make-env))
#t)

I see where this is going--this is for a PL class, and you're extending an existing interpreter so that it can handle strings and string comparisons--but it looks to me like it would help you a lot to add purpose statements to your functions, and test cases for all of them. Start at the top. What is is-string? supposed to do? Write test cases to make sure it does what it's supposed to. Work your way down.
Also, shame on your instructor for giving you test cases :).

Related

In Common Lisp, when are objects referenced and when are they directly accessed by value?

I was reading this question to try and get some insight into the answer. It specifically asks about pass-by-reference, and all of the answers seem to indicate there is no support for pass-by-reference. However, this answer would imply that, while pass by reference may not be supported, some values are indeed accessed by reference. A simpler example would involve cons cells; I can pass a cons cell to a function, and change it's cdr or car to whatever I please.
Ultimately I'd like to know if there is some clear delimination between (to use C# parlance) value-types and reference-types, and if there's any way (more convenient than the answer referenced above) to treat a value as a reference-type.
There is no distinction: all objects are passed by value in Lisp (at least in all Lisps I know of). However some objects are mutable, and conses are one such type. So you can pass a cons cell to a procedure and mutate it in that procedure. Thus the important consideration is whether objects are mutable or not.
In particular this (Common Lisp) function always returns T as its first value, even though its second value may not have 0 as its car or cdr.
(defun cbv (&optional (f #'identity))
(let ((c (cons 0 0)))
(let ((cc c))
(funcall f c)
(values (eq c cc) c))))
> (cbv (lambda (c)
(setf (car c) 1
(cdr c) 2)))
t
(1 . 2)
However since Common Lisp has lexical scope, first-class functions and macros you can do some trickery which makes it look a bit as if call-by-reference is happening:
(defmacro capture-binding (var)
;; Construct an object which captures a binding
`(lambda (&optional (new-val nil new-val-p))
(when new-val-p
(setf ,var new-val))
,var))
(defun captured-binding-value (cb)
;; value of a captured binding
(funcall cb))
(defun (setf captured-binding-value) (new cb)
;; change the value of a captured binding
(funcall cb new))
(defun cbd (&optional (f #'identity))
(let ((c (cons 0 0)))
(let ((cc c))
(funcall f (capture-binding c))
(values (eq c cc) c cc))))
And now:
> (cbd (lambda (b)
(setf (captured-binding-value b) 3)))
nil
3
(0 . 0)
If you understand how this works you probably understand quite a lot of how scope & macros work in Lisp.
There is an exception to the universality of passing objects by value in Common Lisp which is mentioned by Rainer in a comment below: instances of some primitive types may be copied in some circumstances for efficiency. This only ever happens for instances of specific types, and the objects for which it happens are always immutable. To deal with this case, CL provides an equality predicate, eql which does the same thing as eq, except that it knows about objects which may secretly be copied in this way and compares them properly.
So, the safe thing to do is to use eql instead of eq: since objects which may be copied are always immutable this means you will never get tripped up by this.
Here's an example where objects which you would naturally think of as identical turn out not to be. Given this definition:
(defun compare (a b)
(values (eq a b)
(eql a b)))
Then in the implementation I'm using I find that:
> (compare 1.0d0 1.0d0)
nil
t
so double-precision float zero is not eq to itself, always, but it is always eql to itself. And trying something which seems like it should be the same:
> (let ((x 1.0d0)) (compare x x))
t
t
So in this case it looks like the function call is not copying objects but rather I started off with two different objects coming from the reader. However the implementation is always allowed to copy numbers at will and it might well do so with different optimisation settings.

Can `match` in Racket have patterns with variables from an outer scope?

Consider the following example:
#lang racket
(match '(cat . doge)
[`(,a . ,b)
(match b
[a #t]
[_ #f])]
[_ "Not a pair"])
This is what I might write if I wanted to match pairs where the head and tail are the same. This doesn't work though because the second a is bound as a new variable (and matches anything). Are there any pattern forms which allow me to use the previously bound a from the outer scope?
I know this can be achieved in the following way
(match* ('cat 'doge)
[(a a) #t]
[(_ _) #f])
but I still would like to know if there is a way to get that variable from the outer scope (or if there is a reason for not doing so, like some potential name collision problem or something).
Use ==:
(match '(cat . doge)
[`(,a . ,b)
(match b
[(== a) #t]
[_ #f])]
[_ "Not a pair"])
Due to the placement in the docs, == is easy to overlook.

What is the clojure equivalent for Haskell's <-?

I'm trying to figure out the IO monad and the <- syntax which I often see in Haskell code. I've seen it used with multiple datatypes, including arrays and IO.
What is the equivalent operation in clojure if I were to specify one myself?
Do-notation is just sugar for the standard monad operations. For example, if you have something like this:
do
x <- someMonad
return (someFunction x)
That's equivalent to this:
someMonad >>= \x -> return (someFunction x)
So the equivalent Clojure using one of the many monad libraries might be something like this:
(m-bind some-monad (fn [x] (m-result (some-function x))))
Using algo.monads, we can define an IO monad easily (if unnecesarrily).
In Haskell, the IO monad is type IO a = World -> (a, World). It's handy to think of this as an action - something which takes the world, does something, and returns a value and the world.
Using a vector instead of a tuple, this means that, in Clojure, an IO action (a monadic value of the IO monad) looks something like this:
(fn [world]
; some stuff
[value world])
To do something interesting, we need a couple of actions: get-char and put-char.
get-char is an action which takes in the world, reads a char, and returns that char as its value alongside the world:
(defn read-char
[]
(-> *in* .read char))
(defn get-char
[world]
[(read-char) world])
put-char takes a character and creates an action which, given a world, prints the character and returns some (inconsequential) value:
(defn put-char
[c]
(fn [world]
(print c)
[nil world]))
Note that, to make an action happen, we have to supply a world. For instance, (put-char \a) will return an action; ((put-char \a) :world) will invoke that action, printing a and returning [nil :world].
Composing these actions is potentially a very messy process. If, for example, you wanted to get a character, then print it, you'd have to call get-char, unpack its character and world, create an action for that character with put-char, then pass the world to that action.
On the other hand, if we define a monad, we get domonad (the equivalent to Haskell's do) for free. This syntactic sugar alleviates the unpacking/packing boilerplate. We just need a few functions: m-result and m-bind (m-zero and m-plus are also handy, but not necessary).
m-result (return in Haskell) takes a value and wraps it up as an action:
(fn [v]
(fn [world]
[v world]))
m-bind (>>= in Haskell) takes an action and a function which takes a regular value to produce an action, "unwraps" the value by invoking the action, and applies the function to it. With the IO monad, that looks like this:
(fn [io f]
(fn [world]
(let [[v new-world] (io world)]
((f v) new-world))))
So, using algo.monads, we can define io-m as follows:
(defmonad io-m
[m-result (fn [v]
(fn [world]
[v world]))
m-bind (fn [io f]
(fn [world]
(let [[v new-world] (io world)]
((f v) new-world))))])
Now that we've got the primitive IO actions and a means of composing them, we can create more interesting ones. Note that Haskell's unpacking operator (<-) is implicit and the result is automatically wrapped with m-result so we don't use Haskell's return statement to terminate the expressions:
(declare get-rest-of-line)
(def get-line
(domonad io-m
[c get-char
line (if (= c \newline)
(m-result "")
(get-rest-of-line c))]
line))
(defn get-rest-of-line
[c]
(domonad io-m
[cs get-line]
(str c cs)))
(defn put-line
[s]
(if (seq s)
(domonad io-m
[_ (put-char (first s))
_ (put-line (subs s 1))]
_)
(put-char \newline)))
Finally, we can write a program in terms of these IO actions:
(def run-program
(domonad io-m
[line get-line
:let [reversed-line (->> line reverse (apply str))]
_ (put-line reversed-line)]
_))
(run-program :world)
I think Chuck has answered your main question, but in case you'd like to investigate the way the monad operations can be implemented in Clojure using algo.monads as an example, the following:
(domonad state-m
[_ (set-state "foo")
x (fetch-state)]
x)
is equivalent (well, almost, see below) to Haskell's
do
_ <- put "foo" -- see below for a comment on this
x <- get
return x
In algo.monads the <- disappears, because effectively it is implied on every line.
About the "almost" and the _ above: _ actually isn't magic in Clojure and it will be bound to the value returned by set-state, but it's idiomatic to use this symbol as the name of locals one doesn't care about. Of course in Haskell it would be more usual simply to write put "foo" instead of _ <- put "foo".

How to implement a macro system into my LISP

I'm writing my own LISP based on Write Yourself a Scheme in 48 hours. (The code is here.) As a last exercise I want to implement macros. How can this be done considering that I represent expressions as a list of immutable datatypes. Can this be done simply in LISP itself or do I have to implement some function in Haskell?
My current implementation is written in Haskell and pretty much works like this:
Parse input and turn it into a list of expressions
Evaluates the expressions and substitute it tills it's a single expression
Return that expression and print it
The expressions is represented in Haskell like this:
data Expr
= Sym String
| List [Expr]
| Num Int
| Str String
| Bool Bool
| Func Env [String] Expr
| Prim ([Expr] -> ErrorOr Expr)
| Action ([Expr] -> IOErrorOr Expr)
Okey, now to the real problem. Macros doesn't evaluates its arguments but instead transforms into an expression by "placing" the arguments inside the form. Returning valid expression that may be evaluated or returned as a quoted list. I was thinking of implementing this by having a special evaluation function which only evaluates the symbols in the macros' form. How this could be achieved though is something I have problem understanding. The proper solution feels like I should "simply" modify the form by replacing the symbols inside it with the arguments, but that's not possible due to Haskell's immutability.
So, Clojure seems to have implemented macros in Lisp itself though. I can't interpret Clojure's solution but if this can be done it feels like being a bit easier than doing it in Haskell. I have no idea what macroexpand1(which macroexpand call) do, does it call some function from within Clojure's implementation? If so, then I still have to implement it inside Haskell.
If we look at how functions are evaluated:
eval env (List (op:args)) = do
func <- eval env op
args <- mapM (eval env) args
apply func args
apply :: Expr -> [Expr] -> IOErrorOr Expr
apply (Prim func) args = liftToIO $ func args
apply (Action func) args = func args
apply (Func env params form) args =
case length params == length args of
True -> (liftIO $ bind env $ zip params args)
>>= flip eval form
False -> throwError . NumArgs . toInteger $ length params
apply _ _ = error "apply"
So, if I wanna implement a macro system, then I could probably remove the evaluation part of the arguments, then bind the macros parameters to its arguments, and have a special eval which only evaluates every symbol in the form, returning a new form that has the arguments put inside it instead. This is what I can't implement though, and I'm not even sure the logic is correct.
I understand this question is quite wide and could probably be more simply asked with "How do I implement a macro system in my LISP implementation written in Haskell
You might try reading the interpreter implementations in Structure and Implementation of Computer Programs. The eval function that you show clearly only works for the default evaluation rule, and not for what the book calls special forms.
A normal Lisp eval function looks more like this:
eval env expr#(List _)
| isSpecialForm env expr = evalSpecial env expr
| otherwise = evalApplication env expr
evalApplication env (op:args) = do
func <- eval env op
args <- mapM (eval env) args
apply func args
evalSpecial env expr#(List (op:args))
| isMacro env op = eval env (macroExpand env expr)
| otherwise = case op of
"lambda" -> ...
"if" -> ...
-- etc.
No, macros can not be implemented in Lisp itself, that's the whole point to them. You have to macroexpand each macro call according to its definition, as part of loading/compiling/processing a given expression.
You would have to alter your eval implementation to call macros on unevaluated arguments, and feed the results back into eval (not apply, like processing the normal function application would). As suggested by sepp2k in the comments, you'd represent your macros as Func... expressions, but hold them in a separate environment, where only macros are stored.
see also: Lazy Evaluation vs Macros
You don't need a special version of apply. Just call the regular apply without evaluating the arguments and then eval the expression returned by apply.

Representing undefined result in MIT Scheme

Imagine I have a function with a domain of all integers bigger than 0. I want the result of other inputs to be undefined. For the sake of simplicity, let's say this is the increment function. In Haskell, I could achieve this with something like
f :: Integer -> Integer
f x
| x > 0 = x + 1
| otherwise = undefined
Of course, the example is quite gimped but it should be clear what I want to achieve. I'm not sure how to achieve the similar in Scheme.
(define (f x)
(if (> x 0)
(+ x 1)
(?????)))
My idea is to just stick an error in there but is there any way to replicate the Haskell behaviour more closely?
Your question is related to this one which has answers pointing out that in R5RS (which I guess MIT scheme partially supports?), the if with one branch returns an "unspecified value". So the equivalent to the haskell code should be:
(define (f x)
(if (> x 0)
(+ x 1)))
You probably already know this: in haskell undefined is defined in terms of error, and is primarily used in development as a placeholder to be removed later. The proper way to define your haskell function would be to give it a type like: Integer -> Maybe Integer.
A common undefined value is void defined as (define void (if #f #f)).
Notice that not all Scheme implementations allow an if without the alternative part (as suggested in the other answers) - for instance, Racket will flag this situation as an error.
In Racket you can explicitly write (void) to specify that a procedure returns no useful result (check if this is available in MIT Scheme). From the documentation:
The constant #<void> is returned by most forms and procedures that have a side-effect and no useful result. The constant #<undefined> is used as the initial value for letrec bindings. The #<void> value is always eq? to itself, and the #<undefined> value is also eq? to itself.
(void v ...) → void?
Returns the constant #<void>. Each v argument is ignored.
That is, the example in the question would look like this:
(define (f x)
(if (> x 0)
(+ x 1)
(void)))
Speaking specifically to MIT Scheme, I believe #!unspecific is the constant that is returned from an if without an alternative.
(eq? (if (= 1 2) 3) #!unspecific) => #t

Resources