So here is my problem (generalized to an abstract situation). It is generally an interpreter.
I have got a program that needs to parse an input list and according to its elements sequentially call some functions that need to modify variables. Functions are defined separately and chosen by (cond . Those 3 variables that I need to update contain information about current situation (exactly - robot position, maze and robot orientation). The result of previous function is used in the next function (i.e. the updated variables are used).
(define func-a ... )
(define func-b ... )
(define (main-func <maze> <orientation> <coordinates> <list with commands>)
;; here I parse the list and choose which function to call
;; output must contain (list <new-maze> <new-orientation> <new-coordinates>))
)
What scheme tools can I use to update those variables? I have considered several options:
use (define and then call set! (this is bad style cause it is not pure functional programming);
call functions from back to beginning (this won't work: I also have to check if movement is valid);
don't make those variables constant at all, try passing them as arguments to each function;
Is there any other proper way to do it?
You have to keep some state (as well as read a file), so there will not be a pure functional programming, and you have to accept some deviations.
The general approach is to keep the shared object as a local in some meta-function, say parse, and update it by calling those your function, say parse-one, parse-two, and so on.
Now you need a way to update them.
You can make them visible for parse-one and parse-two by defining them inside the scope:
(let ((state (make-state)))
(let ((parse-one (lambda () ...))
(parse-two (lambda () ...)))
....))
Or you use the return value:
(let ((state (make-state)))
...
(set! state (parse-one state))
...)
There is a third approach, called OOP. Define all of them in a single closure, so they can share some data:
(define (make-parser)
(let ((state (make-state))
(let (((parse-one (lambda () ...))
((parse-two (lambda () ...))
((get-state (lambda () state)))
(list parse-one parse-two get-state))))
(destructuring-bind (parse-one parse-two get-state) (make-parser)
...
(parse-one)
...
(get-state))
(destructuring-bind is just an easy way to destruct a list, see it's scheme implementation) But it seems to be a complicated version of the first.
Just because Scheme is considered a 'functional language' doesn't forbid you from using 'set!' - after all it exists in the language to be used. Thus there is nothing wrong with:
(define-record-type position (fields x y z))
(define robot-position (make-position 0.0 0.0 0.0))
(define update-robot-position (new-x new-y new-z)
(set! robot-position (make-position new-x new-y new-x)))
[I've chosen to define positions as invariant.]
You can chose another approach if you want but fundamentally the position of the robot changed and that change will be in your code is some fashion. Why not use the simplest, most straight-forward approach?
Related
My goal is to be able to apply a macro to an argument list in the same way the apply primitive procedure applies a procedure to an argument list.
The list will already be evaluated at the time of application of the macro, there is no way around that and that’s fine; I am wondering if there is any way to programmatically “splice” the list into the macro application (in the same sense as with unquote-splicing). The difficulty resides in that one cannot pass the macro identifier as an argument.
One use case would be
(apply and list)
which would be equivalent to
(not (memq #f list))
to see if there is a #f in list.
Preferably this would be R7RS conformant.
One sort of hacky way would be (as suggested on reddit)
(eval (cons 'and list))
but this is not R7RS conformant, as eval must take an environment argument and it seems to me the standard doesn’t specify how to snatch the environment in effect at the call to eval.
Another half solution is the following, which only works if the list is given directly as a parenthesized sequence of values:
(syntax-rules ()
((_ identifier (val ...))
(identifier val ...)))
I'm posting this as a partial answer I found to my own question, and I'll accept it in a few days if nothing new pops up.
The following works, but only if the macro to apply is contained in a library.
(import (scheme base)
(scheme eval)
(scheme write))
(define (apply-macro mac args . libs)
(eval (cons mac args)
(apply environment libs)))
(define list '(#f #t #t #t))
(display (apply-macro 'and list '(scheme base))) ; => #f
(display (apply-macro 'and (cdr list) '(scheme base))) ; => #t
You can't do that; macros apply to syntax, transforming code fragments into other code fragments, not to values.
Even if you could do it, it would not be equivalent to applying and, since all the elements of list would be evaluated.
For instance, if you define the non-terminating procedure,
(define (forever) (forever))
then (and #f (forever)) is #f, but (apply and (list #f (forever))) would not terminate.
You cannot do this without eval. You would need to implement a procedure version of AND.
The reason it's impossible is because macro expansion is one phase and evaluation is a later phase. The list is piece of dynamic data existing only in the later phase, so a macro cannot use that.
Clojure, being a Lisp dialect, inherited Lisp's homoiconicity. Homoiconicity makes metaprogramming easier, since code can be treated as data: reflection in the language (examining the program's entities at runtime) depends on a single, homogeneous structure, and it does not have to handle several different structures that would appear in a complex syntax [1].
The downside of a more homogeneous language structure is that language constructs, such as loops, nested ifs, function calls or switches, etc, are more similar to each other.
In clojure:
;; if:
(if (chunked-seq? s)
(chunk-cons (chunk-first s) (concat (chunk-rest s) y))
(cons (first s) (concat (rest s) y)))
;; function call:
(repaint (chunked-seq? s)
(chunk-cons (chunk-first s) (concat (chunk-rest s) y))
(cons (first s) (concat (rest s) y)))
The difference between the two constructs is just a word. In a non homoiconic language:
// if:
if (chunked-seq?(s))
chunk-cons(chunk-first(s), concat(chunk-rest(s), y));
else
cons(first(s), concat(rest(s), y));
// function call:
repaint(chunked-seq?(s),
chunk-cons(chunk-first(s), concat(chunk-rest(s), y)),
cons(first(s), concat(rest(s), y));
Is there a way to make these program constructs easier to identify (more conspicuous) in Clojure? Maybe some recommended code format or best practice?
Besides using an IDE that supports syntax highlighting for the different cases, no, there isn't really a way to differentiate between them in the code itself.
You could try and use formatting to differentiate between function calls and macros:
(for [a b]
[a a])
(some-func [a b] [a a])
But then that prevents you from using a one-line list comprehension using for; sometimes they can neatly fit on one line. This also prevents you from breaking up large function calls into several lines. Unless the reducing function is pre-defined, most of my calls to reduce take the form:
(reduce (fn [a b] ...)
starting-acc
coll)
There are just too many scenarios to try to limit how calls are formatted. What about more complicated macros like cond?
I think a key thing to understand is that the operation of a form depends entirely on the first symbol in the form. Instead of relying on special syntaxes to differentiate between them, train your eyes to snap to the first symbol in the form, and do a quick "lookup" in your head.
And really, there are only a few cases that need to be considered:
Special forms like if and let (actually let*). These are fundamental constructs of the language, so you will be exposed to them constantly.
I don't think these should pose a problem. Your brain should immediately know what's going on when you see if. There are so few special forms that plain memorization is the best route.
Macros with "unusual" behavior like threading macros and cond. There are still some instances where I'll be looking over someone's code, and because they're using a macro that I don't have a lot of familiarity with, it'll take me a second to figure out the flow of the code.
This is remedied though by just getting some practice with the macro. Learning a new macro extends your capabilities when writing Clojure anyway, so this should always be considered. As with special forms, there really aren't that many mind-bending macros, so memorizing the main ones (the basic threading macros, and conditional macros) is simple.
Functions. If it's not either of the above, it must be a function and follow typical function calling syntax.
I'm writing a program in which i have to reuse code from one of my professors. My program is written in Racket and the code i want to reuse is written in r6rs.
When I want to test my program it always fails.
This is because I call a procedure with as argument a list (racket list), but that procedure is in the R6RS file. In the R6RS file there is (assert (list? argument)) , this is always false...
Here a simple example :
Racket code :
#lang racket
(require "test2.ss")
(define a (list 1 2 3))
(b a)
R6RS code :
#!r6rs
(library
(test)
(export b)
(import (rnrs base (6))
(rnrs control (6))
(rnrs lists (6))
(rnrs io simple (6)))
(define (b a)
(display "a is : ") (display a) (newline)
(display "list? : ") (display (list? a)) (newline)))
The list? test in the R6RS file is always false... even if I pass as argument a newly created list like in the above example.
How can I do the same as in the example above, so that the list? tests results true.
Thanks for your help!
EDIT : I could not find a r6rs test that results in true on a immutable list, but I found another way to resolve my problem (by passing a mutable list to the procedure).
Racket pairs are different from Scheme pairs since Racket pairs are immutable while Scheme pairs are not.
As far as I know, there is no way to check for Racket's immutable lists in pure RnRS Scheme. However, it is possible to use Scheme's mutable lists in Racket (though of course that isn't really recommended).
#lang racket
(require compatibility/mlist
"test2.ss")
(define a (mlist 1 2 3))
(b a)
Here's an excerpt from the documentation for compatibility/mlist:
This compatibility/mlist library provides support for mutable lists. Support is provided primarily to help porting Lisp/Scheme code to Racket.
Use of mutable lists for modern Racket code is strongly discouraged. Instead, consider using lists.
Still, if you need to interact with Scheme code, that's probably your only reasonable option.
This is just an addendum to Alexis King's answer (code examples can't be in comments). Since the r6rs language (as implemented in Racket) uses mutable lists, and all racket libraries expect immutable lists, you can't reuse the r6rs code as-is. The fastest way to reuse the code is to port it to the #lang racket language.
Change the language, remove the import statement, and then fix each error one at a time.
#lang racket
(define (b a)
(display "a is : ") (display a) (newline)
(display "list? : ") (display (list? a)) (newline)))
When you say your code is written in Racket. Do you mean Racket, the software, or #!racket, one of the multiple compatible languages that Racket (the software) supports?
Since your library is written in #!r6rs, you either need to port it to a #!racket module or you main program can be written in #!r6rs and you can use the library as is. A third option is to make mutable lists to pass to the library function and convert back but or ban lists all togerther, but I find this option somewhat suboptimal.
To do full #!r6rs you need to install your library like this:
plt-r6rs --force --install ./test.sls
I assume test.sls is in the current directory. You'll get a confirmation. you need not restart DrRacket. (Force is not needed, but it will overwrite an earlier version.) Then you just change your code to be Scheme code:
#!r6rs
(import (rnrs)
(test))
(define a (list 1 2 3))
(b a) ; #<void> (and prints stuff to stdout)
Hit [Run] in DrRacket and see the magic!
In Clojure, hash-maps and vectors implement invoke, so that they can be used as functions, for example
(let [dict {:species "Ursus horribilis"
:ornery :true
:diet "You"}]
(dict :diet))
lein> "You"
or, for vectors,
(let [v [42 613 28]]
(v 1))
lein> 613
One can make callable objects in Clojure by having them implement IFn. I'm new-ish to Common Lisp -- are callable objects possible and if so what would implementing that involve? I'd really like to be able to do things like
(let ((A (make-array (list n n) ...)))
(loop for i from 0 to n
for j from 0 to m
do (setf (A i j) (something i j)))
A)
rather than have code littered with aref. Likewise, it would be cool if you could access entries of other data structures, e.g. dictionaries, the same way.
I've looked at the wiki entry on function objects in Lisp/Scheme and it seems as if having a separate function namespace will complicate matters for CL, whereas in Scheme you can just do this with closures.
Example of callable objects in a precursor of Common Lisp
Callable objects have been provided before. For example in Lisp Machine Lisp:
Command: ("abc" 1) ; doesn't work in Common Lisp
#\b
Bindings in Common Lisp
Common Lisp has separate namespaces of names for functions and values. So (array 10 1 20) would only make sense, when array would be a symbol denoting a function in the function namespace. Thus the function value then would be a callable array.
Making values bound to variables act as functions mostly defeats the purpose of the different namespaces for functions and values.
(let ((v #(1 2 3)))
(v 10)) ; doesn't work in Common Lisp
Above makes no sense in a language with different namespaces for functions and values.
FLET is used for functions instead of LET.
(flet ((v #(1 2 3 4 5 6 7))) ; doesn't work in Common Lisp
(v 4))
This would then mean we would put data into the function namespace. Do we want that? Not really.
Literal data as functions in function calls.
One could also think of at least allowing literal data act as functions in direct function calls:
(#(1 2 3 4 5 6 7) 4) ; doesn't work in Common Lisp
instead of
(aref #(1 2 3 4 5 6 7) 4)
Common Lisp does not allow that in any trivial or relatively simple way.
Side remark:
One can implement something in the direction of integrating functions and values with CLOS, since CLOS generic functions are also CLOS instances of the class STANDARD-GENERIC-FUNCTION and it's possible to have and use user-defined subclasses of that. But that's usually not exploited.
Recommendation
So, best to adjust to a different language style and use CL as it is. In this case Common Lisp is not flexible enough to easily incorporate such a feature. It is general CL style to not omit symbols for minor code optimizations. The danger is obfuscation and write-only code, because a lot of information is not directly in the source code, then.
Although there may not be a way to do exactly what you want to do, there are some ways to hack together something similar. One option is define a new binding form, with-callable, that allows us to bind functions locally to callable objects. For example we could make
(with-callable ((x (make-array ...)))
(x ...))
be roughly equivalent to
(let ((x (make-array ...)))
(aref x ...))
Here is a possible definition for with-callable:
(defmacro with-callable (bindings &body body)
"For each binding that contains a name and an expression, bind the
name to a local function which will be a callable form of the
value of the expression."
(let ((gensyms (loop for b in bindings collect (gensym))))
`(let ,(loop for (var val) in bindings
for g in gensyms
collect `(,g (make-callable ,val)))
(flet ,(loop for (var val) in bindings
for g in gensyms
collect `(,var (&rest args) (apply ,g args)))
,#body))))
All that's left is to define different methods for make-callable that return closures for accessing into the objects. For example here is a method that would define it for arrays:
(defmethod make-callable ((obj array))
"Make an array callable."
(lambda (&rest indices)
(apply #'aref obj indices)))
Since this syntax is kind of ugly we can use a macro to make it prettier.
(defmacro defcallable (type args &body body)
"Define how a callable form of TYPE should get access into it."
`(defmethod make-callable ((,(car args) ,type))
,(format nil "Make a ~A callable." type)
(lambda ,(cdr args) ,#body)))
Now to make arrays callable we would use:
(defcallable array (obj &rest indicies)
(apply #'aref obj indicies))
Much better. We now have a form, with-callable, which will define local functions that allow us to access into objects, and a macro, defcallable, that allows us to define how to make callable versions of other types. One flaw with this strategy is that we have to explicitly use with-callable every time we want to make an object callable.
Another option that is similar to callable objects is Arc's structure accessing ssyntax. Basically x.5 accesses the element at index five in x. I was able to implement this in Common Lisp. You can see the code I wrote for it here, and here. I also have tests for it so you can see what using it looks like here.
How my implementation works is I wrote a macro w/ssyntax which looks at all of the symbols in the body and defines macros and symbol-macros for some of them. For example the symbol-macro for x.5 would be (get x 5), where get is a generic function I defined that accesses into structures. The flaw with this is I always have to use w/ssyntax anywhere I want to use ssyntax. Fortunately I am able to hide it away inside a macro def which acts like defun.
I agree with Rainer Joswig's advice: It would be better to become comfortable with Common Lisp's way of doing things--just as it's better for a Common Lisp programmer to become comfortable with Clojure's way of doing things, when switching to Clojure. However, it is possible to do part of what you want, as malisper's sophisticated answer shows. Here is the start of a simpler strategy:
(defun make-array-fn (a)
"Return a function that, when passed an integer i, will
return the element of array a at index i."
(lambda (i) (aref a i)))
(setf (symbol-function 'foo) (make-array-fn #(4 5 6)))
(foo 0) ; => 4
(foo 1) ; => 5
(foo 2) ; => 6
symbol-function accesses the function cell of the symbol foo, and setf puts the function object created by make-array-fn into it. Since this function is then in the function cell, foo can be used in the function position of a list. If you wanted, you could wrap up the whole operation into a macro, e.g. like this:
(defmacro def-array-fn (sym a)
"Define sym as a function that is the result of (make-array-fn a)."
`(setf (symbol-function ',sym)
(make-array-fn ,a)))
(def-array-fn bar #(10 20 30 40))
(bar 0) ; => 10
(bar 1) ; => 20
(bar 3) ; => 40
Of course, an "array" defined this way no longer looks like an array. I suppose you could do something fancy with CL's printing routines. It's also possible to allow setting values of the array as well, but this would probably require a separate symbols.
That is, when you call a function with >1 arity with only one argument, it should, instead of displaying an error, curry that argument and return the resulting function with decreased arity. Is this possible to do using Lisp's macros?
It's possible, but not easy if you want a useful result.
If you want a language that always does simple currying, then the implementation is easy. You just convert every application of more than one input to a nested application, and the same for functions of more than one argument. With Racket's language facilities, this is a very simple exercise. (In other lisps you can get a similar effect by some macro around the code where you want to use it.)
(Incidentally, I have a language on top of Racket that does just this. It gets the full cuteness of auto-curried languages, but it's not intended to be practical.)
However, it's not too useful since it only works for functions of one argument. You could make it useful with some hacking, for example, treat the rest of the lisp system around your language as a foreign language and provide forms to use it. Another alternative is to provide your language with arity information about the surrounding lisp's functions. Either of these require much more work.
Another option is to just check every application. In other words, you turn every
(f x y z)
into code that checks the arity of f and will create a closure if there are not enough arguments. This is not too hard in itself, but it will lead to a significant overhead price. You could try to use a similar trick of some information about arities of functions that you'd use in the macro level to know where such closures should be created -- but that's difficult in essentially the same way.
But there is a much more serious problem, at the highlevel of what you want to do. The thing is that variable-arity functions just don't play well with automatic currying. For example, take an expression like:
(+ 1 2 3)
How would you decide if this should be called as is, or whether it should be translated to ((+ 1 2) 3)? It seems like there's an easy answer here, but what about this? (translate to your favorite lisp dialect)
(define foo (lambda xs (lambda ys (list xs ys))))
In this case you can split a (foo 1 2 3) in a number of ways. Yet another issue is what do you do with something like:
(list +)
Here you have + as an expression, but you could decide that this is the same as applying it on zero inputs which fits +s arity, but then how do you write an expression that evaluates to the addition function? (Sidenote: ML and Haskell "solves" this by not having nullary functions...)
Some of these issues can be resolved by deciding that each "real" application must have parens for it, so a + by itself will never be applied. But that loses much of the cuteness of having an auto-curried language, and you still have problems to solve...
In Scheme it's possible to curry a function using the curry procedure:
(define (add x y)
(+ x y))
(add 1 2) ; non-curried procedure call
(curry add) ; curried procedure, expects two arguments
((curry add) 1) ; curried procedure, expects one argument
(((curry add) 1) 2) ; curried procedure call
From Racket's documentation:
[curry] returns a procedure that is a curried version of proc. When the resulting procedure is first applied, unless it is given the maximum number of arguments that it can accept, the result is a procedure to accept additional arguments.
You could easily implement a macro which automatically uses curry when defining new procedures, something like this:
(define-syntax define-curried
(syntax-rules ()
((_ (f . a) body ...)
(define f (curry (lambda a (begin body ...)))))))
Now the following definition of add will be curried:
(define-curried (add a b)
(+ a b))
add
> #<procedure:curried>
(add 1)
> #<procedure:curried>
((add 1) 2)
> 3
(add 1 2)
> 3
The short answer is yes, though not easily.
you could implament this as a macro that wrapped every call in partial, though only in limited context. Clojure has some features that would make this rather difficult such as variable arity functions and dynamit calls. Clojure lacks a formal type system to concretely decide when the call can have no more arguments and should actually be called.
As noted by Alex W, the Common Lisp Cookbook does give an example of a "curry" function for Common Lisp. The specific example is further down on that page:
(declaim (ftype (function (function &rest t) function) curry)
(inline curry)) ;; optional
(defun curry (function &rest args)
(lambda (&rest more-args)
(apply function (append args more-args))))
Auto-currying shouldn't be that hard to implement, so I took a crack at it. Note that the following isn't extensively tested, and doesn't check that there aren't too many args (the function just completes when there are that number or more):
(defun auto-curry (function num-args)
(lambda (&rest args)
(if (>= (length args) num-args)
(apply function args)
(auto-curry (apply (curry #'curry function) args)
(- num-args (length args))))))
Seems to work, though:
* (auto-curry #'+ 3)
#<CLOSURE (LAMBDA (&REST ARGS)) {1002F78EB9}>
* (funcall (auto-curry #'+ 3) 1)
#<CLOSURE (LAMBDA (&REST ARGS)) {1002F7A689}>
* (funcall (funcall (funcall (auto-curry #'+ 3) 1) 2) 5)
8
* (funcall (funcall (auto-curry #'+ 3) 3 4) 7)
14
A primitive (doesn't handle full lambda lists properly, just simple parameter lists) version of some macro syntax sugar over the above:
(defmacro defun-auto-curry (fn-name (&rest args) &body body)
(let ((currying-args (gensym)))
`(defun ,fn-name (&rest ,currying-args)
(apply (auto-curry (lambda (,#args) ,#body)
,(length args))
,currying-args))))
Seems to work, though the need for funcall is still annoying:
* (defun-auto-curry auto-curry-+ (x y z)
(+ x y z))
AUTO-CURRY-+
* (funcall (auto-curry-+ 1) 2 3)
6
* (auto-curry-+ 1)
#<CLOSURE (LAMBDA (&REST ARGS)) {1002B0DE29}>
Sure, you just have to decide exact semantics for your language, and then implement your own loader which will translate your source files into the implementation language.
You could e.g. translate every user function call (f a b c ... z) into (...(((f a) b) c)... z), and every (define (f a b c ... z) ...) to (define f (lambda(a) (lambda(b) (lambda(c) (... (lambda(z) ...) ...))))) on top of a Scheme, to have an auto-currying Scheme (that would forbid varargs functions of course).
You will also need to define your own primitives, turning the varargs functions like e.g. (+) to binary, and turning their applications to using fold e.g. (+ 1 2 3 4) ==> (fold (+) (list 1 2 3 4) 0) or something - or perhaps just making such calls as (+ 1 2 3 4) illegal in your new language, expecting of its user to write fold forms by themselves.
That's what I meant by "deciding ... semantics for your language".
The loader can be as simple as wrapping the file contents into a call to a macro - which you would then have to implement, as per your question.
Lisp already has Functional Currying:
* (defun adder (n)
(lambda (x) (+ x n)))
ADDER
http://cl-cookbook.sourceforge.net/functions.html
Here's what I was reading about Lisp macros: https://web.archive.org/web/20060109115926/http://www.apl.jhu.edu/~hall/Lisp-Notes/Macros.html
It's possible to implement this in pure Lisp. It's possible to implement it using macros as well, however it seems as though macros would make it more confusing for very basic stuff.