I am attempting to build a rudimentary interpreter in Scheme, and I want to use an association list to map to arithmetic functions. This is what i have so far:
; A data type defining an abstract binary operation
(define binoptable
'(("+" . (+ x y)))
("-" . (- x y))
("*" . (* x y))
("/" . (/ x y)))
)
The problem is the elements on the RHS of the table are stored as lists of symbols. Does anyone have any ideas as to how to remedy his. Thanks in advance.
You probably want:
(define binoptable
`(("+" . ,+)
("-" . ,-)
("*" . ,*)
("/" . ,/)))
Also, you can use a macro to make it easier to specify:
(define-syntax make-binops
(syntax-rules ()
[(make-binops op ...)
(list (cons (symbol->string 'op) op) ...)]))
(define binoptable (make-binops + - * /))
Related
I am trying to combine two lists of x coordinates and y coordinates into pairs in scheme, and I am close, but can't get a list of pairs returned.
The following can match up all the pairs using nested loops, but I'm not sure the best way to out put them, right now I am just displaying them to console.
(define X (list 1 2 3 4 5))
(define Y (list 6 7 8 9 10))
(define (map2d X Y)
(do ((a 0 (+ a 1))) ; Count a upwards from 0
((= a (length X) ) ) ; Stop when a = length of list
(do ((b 0 (+ b 1))) ; Count b upwards from 0
((= b (length Y) ) ) ; Stop when b = length of second list
(display (cons (list-ref X a) (list-ref Y b))) (newline)
))
)
(map2d X Y)
I am looking to have this function output
((1 . 6) (1 . 7) (1 . 8) ... (2 . 6) (2 . 7) ... (5 . 10))
I will then use map to feed this list into another function that takes pairs.
Bonus points if you can help me make this more recursive (do isn't 'pure' functional, right?), this is my first time using functional programming and the recursion has not been easy to grasp. Thanks!
The solutions of Óscar López are correct and elegant, and address you to the “right” way of programming in a functional language. However, since you are starting to study recursion, I will propose a simple recursive solution, without high-level functions:
(define (prepend-to-all value y)
(if (null? y)
'()
(cons (cons value (car y)) (prepend-to-all value (cdr y)))))
(define (map2d x y)
(if (null? x)
'()
(append (prepend-to-all (car x) y) (map2d (cdr x) y))))
The function map2d recurs on the first list: if it is empty, then the cartesian product will be empty; otherwise, it will collect all the pairs obtained by prepending the first element of x to all the elements of y, with all the pairs obtained by applying itself to the rest of x and all the elements of y.
The function prepend-to-all, will produce all the pairs built from a single value, value and all the elements of the list y. It recurs on the second parameter, the list. When y is empty the result is the empty list of pairs, otherwise, it builds a pair with value and the first element of y, and “conses” it on the result of prepending value to all the remaining elements of y.
When you will master the recursion, you can pass to the next step, by learning tail-recursion, in which the call to the function is not contained in some other “building” form, but is the first one of the recursive call. Such form has the advantage that the compiler can transform it into a (much) more efficient iterative program. Here is an example of this technique applied to your problem:
(define (map2d x y)
(define (prepend-to-all value y pairs)
(if (null? y)
pairs
(prepend-to-all value (cdr y) (cons (cons value (car y)) pairs))))
(define (cross-product x y all-pairs)
(if (null? x)
(reverse all-pairs)
(cross-product (cdr x) y (prepend-to-all (car x) y all-pairs))))
(cross-product x y '()))
The key idea is to define an helper function with a new parameter that “accumulates” the result while it is built. This “accumulator”, which is initialized with () in the call of the helper function, will be returned as result in the terminal case of the recursion. In this case the situation is more complex since there are two functions, but you can study the new version of prepend-to-all to see how this works. Note that, to return all the pairs in the natural order, at the end of the cross-product function the result is reversed. If you do not need this order, you can omit the reverse to make the function more efficient.
Using do isn't very idiomatic. You can try nesting maps instead, this is more in the spirit of Scheme - using built-in higher-order procedures is the way to go!
; this is required to flatten the list
(define (flatmap proc seq)
(fold-right append '() (map proc seq)))
(define (map2d X Y)
(flatmap
(lambda (i)
(map (lambda (j)
(cons i j))
Y))
X))
It's a shame you're not using Racket, this would have been nicer:
(define (map2d X Y)
(for*/list ([i X] [j Y])
(cons i j)))
i'm trying to write a code in RACKET , i know how to solve it but i'm having some trouble , i can use your help .
the function will get a list and a specific symbol , and it need to return the number of times that the symbol is shown in the list .
in the test - i'm comparing the result with a number i'm asking and should return true if the number is the same .
i've tried to do it with (if / cond / and even tried acc ) - but there is always something that is missing .
here is my code including the test .
please help me find out how to write it .
the idea of the solution is , the i take the head of the list and i check if it's equal to the symbol i wrote , if it does - n is plus 1 , empty list is equal 0 .
( : counts : (Listof Symbol) -> Integer )
(define (counts a n ) ; a = list of symbols.
(cond [(null? a) 0])
[(eq?(first a) 'x) (= n(+ n 1))]
(counts( (rest a) n)))
;test:
(test (eq? (counts ('a 'b 'x) )1))
There are several problems with your code:
The cond expression is being incorrectly used, and the else case is missing
There are erroneous parentheses, for example at the end of the second line in counts and when you call counts in the fourth line
In the base case of the recursion you must return n, the counter
You must also call the recursion if the symbol was found, in the second case
This part: (= n (+ n 1)) is not doing what you think, it's not changing the value of n, instead is testing for equality between n and (+ n 1) (which will return false, of course)
You're not passing as parameter the symbol being searched, it's hard-coded in the procedure
This is a corrected version of what you intended to write:
(define (counts a x n)
(cond [(null? a) n]
[(eq? (first a) x)
(counts (rest a) x (+ n 1))]
[else
(counts (rest a) x n)]))
Use it like this:
(counts '(a b x c d x e x) 'x 0)
=> 3
I advice you to grab a good book or tutorial, it seems you're struggling with the basic syntax. And learn how to use DrRacket to help with the syntax errors, it's an excellent IDE.
I am trying an example on Chapter 4 of SICP (part of writing the LISP interpreter)
(define (definition-value exp)
(if (symbol? (cadr exp))
(caddr exp)
(make-lambda
(cdadr exp) ; formal parameters
(cddr exp) ; body
)
)
)
(define (make-lambda parameters body)
(cons 'lambda (cons parameters body))
)
I Tested it, definition-value on '(define (double x) (+ x x))) should return a lambda function
( (definition-value '(define (double x) (+ x x))) 10)
Racket outputs
procedure application: expected procedure, given: (lambda (x) (+ x x)); arguments were: 10
Isn't "(lambda (x) (+ x x))" a procedure? Or it is a reference? If it is a reference, any way to "dereference" it?
definition-value returns the value in the definition expression given to it as an argument:
(definition-value '(define x 42))
=> 42
(definition-value '(define (qq x) (+ x y 42)))
=> (make-lambda '(x) '((+ x y 42)))
=> '(lambda (x) (+ x y 42))
You can't call the quoted list as a function, as you do: ( '(lambda (x) (+ x y 42)) 10) is invalid. It is not a function, it is just an s-expression.
definition-value is part of an interpreter. This interpreter is the way to "dereference", i.e. interpret function definitions. Different interpreters can have different ways to interpret same function definitions, giving different semantics to the resulting languages.
Evaluation of expressions must be done in context - they appear inside certain lexical scope (area in code where a variable is visible), which gives rise to environments (also, this). In the example above, y is defined in some enclosing scope in the program being interpreted. Trying to interpret that expression in REPL by calling Racket's eval, what value would y have?
I figured the answer, if execute a Racket script in file, racket interpreter doesn't know the namespace, however, the REPL knows it. The solution is to add this line at the beginning of the file
(define ns (make-base-namespace))
Then pass ns to eval when using it
(eval <what ever code reference here> ns)
That will make my above mentioned examples work.
I'm trying to find the "best" implementation of a multi-argument "compose" in Scheme (I know it's a builtin in some implementations, but assume for the moment I am using one that doesn't have this).
For a 2-argument compose function I have this:
(define compose
(lambda (f g)
(lambda x
(f (apply g x)))))
This has the advantage that if the right-most function needs additional arguments, these can still be passed through the combined function. This has the pleasing property that composing the identity function on top of something does not change the function.
For example:
(define identity
(lambda (x) x))
(define list1
(compose identity list))
(define list2
(compose identity list1))
(list2 1 2 3)
> (1 2 3)
Now to do an "n-argument" compose I could do this:
(define compose-n
(lambda args
(foldr compose identity args)))
((compose-n car cdr cdr) '(1 2 3))
> 3
But this no longer preserves that nice "identity" property:
((compose-n identity list) 1 2 3)
> procedure identity: expects 1 argument, given 3: 1 2 3
The problem is that "initial" function used for the foldr command. It has built:
(compose identity (compose list identity))
So... I'm not sure the best way around this. "foldl" would seem to be the natural better alternative, because I want to it start with "identity" on the left not the right...
But a naive implementation:
(define compose-n
(lambda args
(foldl compose identity args)))
which works (have to reverse the order of function applications):
((compose-n cdr cdr car) '(1 2 3))
> 3
doesn't solve the problem because now I end up having to put the identity function on the left!
((compose-n cdr cdr car) '(1 2 3))
> procedure identity: expects 1 argument, given 3: 1 2 3
It's like, I need to use "foldr" but need some different "initial" value than the identity function... or a better identity function? Obviously I'm confused here!
I'd like to implement it without having to write an explicit tail-recursive "loop"... it seems there should be an elegant way to do this, I'm just stuck.
You might want to try this version (uses reduce from SRFI 1):
(define (compose . fns)
(define (make-chain fn chain)
(lambda args
(call-with-values (lambda () (apply fn args)) chain)))
(reduce make-chain values fns))
It's not rocket science: when I posted this on the #scheme IRC channel, Eli noted that this is the standard implementation of compose. :-) (As a bonus, it also worked well with your examples.)
The OP mentioned (in a comment to my answer) that his implementation of Scheme does not have call-with-values. Here's a way to fake it (if you can ensure that the <values> symbol is never otherwise used in your program: you can replace it with (void), (if #f #f), or whatever you like that's not used, and that's supported by your implementation):
(define (values . items)
(cons '<values> items))
(define (call-with-values source sink)
(let ((val (source)))
(if (and (pair? val) (eq? (car val) '<values>))
(apply sink (cdr val))
(sink val))))
What this does is that it fakes a multi-value object with a list that's headed by the <values> symbol. At the call-with-values site, it checks to see if this symbol is there, and if not, it treats it as a single value.
If the leftmost function in your chain can possibly return a multi-value, your calling code has to be prepared to unpack the <values>-headed list. (Of course, if your implementation doesn't have multiple values, this probably won't be of much concern to you.)
The issue here is that you're trying to mix procedures of different arity. You probably want to curry list and then do this:
(((compose-n (curry list) identity) 1) 2 3)
But that's not really very satisfying.
You might consider an n-ary identity function:
(define id-n
(lambda xs xs))
Then you can create a compose procedure specifically for composing n-ary functions:
(define compose-nary
(lambda (f g)
(lambda x
(flatten (f (g x))))))
Composing an arbitrary number of n-ary functions with:
(define compose-n-nary
(lambda args
(foldr compose-nary id-n args)))
Which works:
> ((compose-n-nary id-n list) 1 2 3)
(1 2 3)
EDIT: It helps to think in terms of types. Let's invent a type notation for our purposes. We'll denote the type of pairs as (A . B), and the type of lists as [*], with the convention that [*] is equivalent to (A . [*]) where A is the type of the car of the list (i.e. a list is a pair of an atom and a list). Let's further denote functions as (A => B) meaning "takes an A and returns a B". The => and . both associate to the right, so (A . B . C) equals (A . (B . C)).
Now then... given that, here's the type of list (read :: as "has type"):
list :: (A . B) => (A . B)
And here's identity:
identity :: A => A
There's a difference in kind. list's type is constructed from two elements (i.e. list's type has kind * => * => *) while identity's type is constructed from one type (identity's type has kind * => *).
Composition has this type:
compose :: ((A => B).(C => A)) => C => B
See what happens when you apply compose to list and identity. A unifies with the domain of the list function, so it must be a pair (or the empty list, but we'll gloss over that). C unifies with the domain of the identity function, so it must be an atom. The composition of the two then, must be a function that takes an atom C and yields a list B. This isn't a problem if we only give this function atoms, but if we give it lists, it will choke because it only expects one argument.
Here's how curry helps:
curry :: ((A . B) => C) => A => B => C
Apply curry to list and you can see what happens. The input to list unifies with (A . B). The resulting function takes an atom (the car) and returns a function. That function in turn takes the remainder of the list (the cdr of type B), and finally yields the list.
Importantly, the curried list function is of the same kind as identity, so they can be composed without issue. This works the other way as well. If you create an identity function that takes pairs, it can be composed with the regular list function.
While it would have been nice for the "empty" list to devolve to the identity function, surrendering this appears to result in the following, which isn't too bad:
(define compose-n
(lambda (first . rest)
(foldl compose first rest)))
((compose-n cdr cdr car) '(1 2 3))
((compose-n list identity identity) 1 2 3)
How do I pass position-independent parameters to scheme functions?
In PLT Scheme you can use:
(define area
(lambda (x #:width y)
(* x y)))
(area 3 #:width 10)
or
(area #:width 10 3)
both would return 30.
There's no standard support for this in scheme but have a look at this
I am not a scheme guru, but I'm thinking that parameters need to be a pair rather than an atom, then you make a parameter list from your pairs and use a let block to bind the values to actual parameters. And, for the love of all that is beautiful, call a helper function to do the actual work with the parameters in the right order since calling get-param in recursion is going to get expensive.
(define get-param (lambda (name pair-list)
(cond ((null? pair-list) nil)
((eq? name (caar pair-list)) (cadr (car pair-list)))
(t (get-param name (cdr pair-list))))))
; position independent subtract always subtracts y from x
; usage (f '(x 7) '(y 9)) => -2
; (f '(y 9) '(x 7)) => -2
(define f (lambda (x-pair y-pair)
(let ((pl (list x-pair y-pair))
(let ((x (get-param 'x pl)) (y (get-param 'y pl))
(- x y)))))
Someone who is really clever would make a factory function that would take an arbitrary lambda expression and build an equivalent position independent lambda from it.