I am very briefly looking into Scheme and wondering if there is a way to do the following: add several operations to each outcome (#t and #f).
(if (something)
Do something //true, #t
Do one thing AND another thing)) //false, #t
As an example, given a defined procedure that takes an integer x. If it is greater than five --> print out a message. If it is less than five --> print out message AND set x to zero:
(if (> x 5)
"Greater than five"
"Less than or equal to 5", (= x 0))
To rephrase: I am looking for a mechanism that allows me to do the following (expressed in Java syntax):
if (cond) { //true
//Do this
}
else { //false
//Do this
//AND this
}
Just make it up as you go !
OK, so say you we're really stuck, you at least know if gives you two branches.
(if #t "a" "b") ; => "a"
(if #f "a" "b") ; => "b"
Well "a" and "b" could be anything, right? What if they were procedures instead?
(define (a) "10")
(define (b) "20")
(if #t (a) (b)) ; => "10"
(if #f (a) (b)) ; => "20"
OK and we know procedure bodies can evaluate any number of expressions in sequence. So we could expand a and b to something like
(define (a) (print "a is ") (print "10") (newline))
(define (b) (print "b is ") (print "20") (newline))
(if #t (a) (b)) ; "a is 10\n"
(if #f (a) (b)) ; "b is 20\n"
OK so maybe that's a little cumbersome to define a procedure every time you want a logic branch that needs to eval multiple expressions, but at least it works. You could then inline the procedures with lambdas to make your life a little easier
((if #t
(λ ()
(print "a")
(print "b")
(newline))
(λ ()
(print "c")
(print "d")
(newline)))) ; "ab\n"
((if #f
(λ ()
(print "a")
(print "b")
(newline))
(λ ()
(print "c")
(print "d")
(newline)))) ; "cd\n"
Well now you can't really say you're stuck anymore. Things may not look exactly the same way they do in Java (thankfully), but at least things are behaving as expected.
As you continue to learn the language and common idioms, you might stumble across cond and begin. They might make your life easier, but you have to understand there's nothing magical about them. You could've just have easily implemented these yourself.
You can make up everything as you go. This is one of the reasons I love scheme/racket. Next to nothing is holy/sacred and you can essentially implement anything you can imagine.
Here's the thing though, if in scheme is a lot different from if in the algol family. If in algol derivatives is a branch or conditional jump instruction; if directly alters the flow of the code. In scheme/lisps every if returns a value. It isn't quite a full function is lisps due to the limitation of the internal structure of the interpreter or compiler, but for most purposes you can treat it as just another function.
(if (something)
Do something //true, #t
Do one thing AND another thing)) //false, #t
Is wrong, what is really going on.
(if condition
(return value of this first exp) //true value
(return value or this second exp)) //false value
In scheme, when you want a function to have a side-effect, that is mutate state you have to be very explicit and it's a good idea to mark function that mutate state with a "!" at the end of the function name.
Procedures like set! vector-set! and the like return an unspecified value. If you want a side effect and a specific value or more than one side effect in a particular sequence, you have to wrap the whole thing up with begin. Additionally if you just (set! x 0) you only change the value of x in the local scope, which may not be what you wanted to do . Whatever bound symbol you used to pass x into the function still carries it's old value.(set-car, vector-set! and set-cell-contents! do modify the underlying state of the data structure called across lexical boundaries) Explicit recursion or hiding a value in a closure is often appropriate.
The syntax for begin is (begin exp1 ... expN). Begin evaluates each expression in turn, and returns the value of the last expression. The only was this is useful is if all expressions before the last create side effects (mutate state or perform I/O). Also keep in mind both define and each clause of a cond contain and implicit begin.
In Java the procedure that prints a string creates side effect. If is not the same as simply returning a string, which is what your first branch of the (if (> x 5) .. is doing.
So to simplify things, we will keep the string printing as a side effect, and the next or new value of x as the return value of the statment.
(cond ((> x 5) (display "Greater than five") (newline) x)
(else (display "Less than or equal to 5") (newline) 0))
or the nearly equivalent
(if (> x 5)
(begin (display "Greater than five") (newline) x)
(begin (display "Less than or equal to 5") (newline) 0))
Just use begin, which is pretty similar to a λ expression:
(if #t
(begin (displayln "Hello, world!") (displayln "wtf"))
(displayln "stdio.h"))
You can wrap pretty much anything you like into a begin expression. They are usually used for flow control, because everything within a begin is evaluated first, but since if is a macro (Created with define-syntax instead of define) it treats begin as just another expression.
Related
I need help to understand my code theoretically. Here is my lisp program:
(defun depth (lst)
(if (or (null lst) (atom lst)) 0
(+ 1 (apply 'max (mapcar #'depth lst)))
))
I know it works with this example:
(write (depth '((a (b c) d r ((t))))) -> 3
I just can't understand the else statement of the IF statement that I tried.
If you can help me, it will be very much appreciated. Thank you in advance.
Here is your code, slightly reformatted:
(defun depth (value)
(if (or (null value) (atom value))
0
(+ 1 (apply 'max (mapcar #'depth value)))))
I renamed lst (you could have written it list, by the way) to value, because the name is confusing as it suggest that the variable is always a list, which is not true. The function depth can be called on any value:
(depth "hello")
=> 0
(depth 100)
=> 0
The then branch of the if is evaluated when value is NIL or any atom. Since NIL is also an atom, the test expression could be simplified as (atom value). When value is an atom, the depth is zero.
The else branch of the if is evaluated when value is not an atom, which by definition of atom means value here is a cons. The function also assumes that it is a proper list, and not some circular list.
Since value is a list in that branch, we can call mapcar on it: (mapcar #'depth value); this is where the function assumes the list is proper.
This computes (depth v) for each v in value. More precisely if value is a list of length n, then that call to mapcar evaluates as a list of numbers (D1 ... Dn) where Di is (depth Vi) for all i between 1 and n.
So we know that (apply 'max (mapcar ...)) is (apply 'max depths) for some list depths of numbers. In general:
(apply fn v1 ... vn list)
... is a way to call the function object denoted by the fn expression with at least n elements (v1 to vn), as well as an arbitrary number of additional elements stored in list. When you quote the function, as 'max, or when you write #'max, you refer to a function by its name in the function namespace.
Contrast this to the usual way of calling a function:
(f x y z)
The function name and the number of arguments being passed is fixed: as soon the form is read we knows there is a call to f with 3 arguments.
The apply function is a built-in that allows you to pass additional arguments in a list, in the last call argument. The above call could be written:
(apply #'f x y z ()) ;; note the empty list as a last argument
This could also be written:
(apply #'f (list x y z)) ;; all arguments in the last list
The only difference is probably a matter of runtime efficiency (and with good compilers, maybe there is no difference).
In your example, you do:
(apply max depths)
Which would be the same as writing (pseudo-code):
(max d1 d2 d3 ... dn)
... where depths is the list (list d1 d2 ... dn).
But we can't literally write them all directly, since the content of the list is only known at runtime.
Thus, the call to apply computes the max depths among all the depths computed recursively. Note that the above is a somewhat improper use of apply, since apply should not be called with lists of arbitrary size: there is a limit in the standard named CALL-ARGUMENTS-LIMIT that is allowed to be as low as 50 in theory, the maximum size of such a list (we will see an alternative below).
Finally, depth evaluates (+ 1 ...) on this result. In other words, the whole expression can be summarized as: the depth of a list is 1 added to the maximum depth of all its elements.
Using reduce
Instead of apply, you can use REDUCE to compute max successively on a list. This is preferable to apply because:
there is no limitation for the number of elements, like apply
(reduce 'max depths) ;; works the same, but more reliably
there is no need need to build an intermediate list of depths, you iterate over the list of values, call depth and directly use the result to compute the max. The skeleton is:
(reduce (lambda (max-so-far item) ...)
value
:initial-value 0)
Declarative approach
Instead of reduce, the loop macro can be used as a more readable alternative to express the same computation. I also use typecase which in my opinion makes the intent clearer:
(defun depth (value)
(typecase value
(atom 0)
(cons (1+ (loop for v in value maximize (depth v))))))
Is there a type-safe list-ref function provided by Typed Racket?
The list-ref function appears to throw an error if you try to access an index that is out of bounds:
> (require typed/racket)
> (list-ref '(1 2 3) 100)
; list-ref: index too large for list
; index: 100
; in: '(1 2 3)
It makes sense that list-ref returns an error given its type:
> list-ref
- : (All (a) (-> (Listof a) Integer a))
I would imagine that a type-safe version would have a type like the following:
(: list-ref (All (a) (-> (Listof a) Integer (Option a)))
If this type-safe list-ref function is provided somewhere from Typed Racket, how would I have gone about finding it?
If this type-safe list-ref function doesn't exist, then why not? It seems like this function would be generally useful.
It doesn't exist as far as I know.
One problem with your proposed (All (a) (-> (Listof a) Integer (Option a))) is that (Option a) is simply (U #f a). That is, you must represent "none" with #f. But if you have a (Listof Boolean), and list-ref* (your variant of list-ref) returns #f, how can you tell if it's because to the index is out of bounds, or because the element is truly #f?
One possible way to fix this problem is by wrapping the "some" variant with something like a box, and adjust the type accordingly. E.g.,
(: list-ref* (All (a) (-> (Listof a) Integer (Option (Boxof a)))))
(define (list-ref* xs i)
(with-handlers ([exn:fail? (λ (_) #f)])
(box (list-ref xs i))))
Mind you that wrapping will affect performance, and this might explain why it's not included in the library.
Is there a way in lisp-family (EDIT: lisp-1) languages to differentiate symbol evaluation with regard to its position as as function or as an argument (i.e. override eval of this symbol in regard to when it is evaluated)?
As an example (I don't need this functionality, this is an example), I wanted to implement some sort of infix operation on a set of objects, which can be called by an object itself
(my-obj some-operator arg1 ...)
which will actually apply function some-operator to my-obj and arguments.
But when this object is used anywhere else in code as an argument, like:
(some-function my-obj &args...)
it will evaluate to a value of my-obj.
Thank you.
In Racket it is possible to do a couple things in this spirit:
You can define a struct and give it a prop:procedure. When an instance of the struct is supplied in an application, the procedure will be called.
You can override the default #%app with your own function, to redefine application generally, and including things that aren't structs. For example you can do things like emulate Clojure's (key map) syntax, so that ('symbol dict) is actually (hash-ref dict 'symbol).
Being a lisp-1 basically means that you do not evaluate the first slot of a combination any differently than any other slots. To get such behavior for code you write anyway, you need to transform it to code that does what you want under the rules of a lisp-1. Thus you will need to implement a macro that performs this transformation.
For example if you want infix operators you need to write some macro infix and then perhaps you could write:
(infix (+ - * /) (1 + 2 * 5 - 3) / 4)
and have it evaluate to 2.
I have been playing around with the idea of a default procedure in a OO CLOS-like Scheme. eg. that writing
(obj 5 10)
Would validate obj and apply it with arguments if obj is a procedure or method, but if it isn't it would be the same as the default dispatcher eg.
(default-dispatcher obj 5 10)
In such Scheme one could make vector accessors:
(define-method default-dispatcher
"Default dispatcher for vectors"
([obj %vector] [index %number]) -> (vector-ref obj index)
([obj %vector] [index %number] value) -> (vector-set! obj index value)
(args ...) -> (error "No such method"))
; example usage
(define vec (vector 4 5 6 7))
[vec 1] ; => 5
[vec 1 10]
[vec 1] ; => 10
In Racket this is possible by changing the languages #%app syntax.
In the TXR Lisp dialect, the problem is approached from the other end. Starting with Lisp-2 dialect as a basis, can we robe ourselves with some of the expressivity advantages of a Lisp-1 dialect, like eliminating the (function ...), #' and funcall noise from programs that make extensive use of higher order functions?
The design is centered around a special operator called dwim, which stands for either "Do What I Mean" or "Dispatch, in a Way that is Intelligent and Meaningful".
Invocations of the dwim operator are sugared over using square brackets, which are called "DWIM Brackets"
The dwim operator isn't just a macro over Lisp-2; it actually changes the name lookup rules. When we have
(dwim a b c (d e f) g)
Or equivalently:
[a b c (d e f) g]
all of the argument forms which are symbolic (a, b, c and g) are resolved using a special rule which conflates together the function and variable namespaces. This is built into the heart of the language. The operator has direct access to the environment to make this possible.
The special treatment does not recurse into (d e f), which is an ordinary Lisp-2 form. You have to put the DWIM Brackets on that if you want the semantics.
Also, the dwim operator is properly handled by macro expansion. For instance, given:
(symacrolet ((localfun whatever))
(flet ((localfun () ...)))
[a b c localfun] ;; refers to the flet as a function object!
(a b c localfun))) ;; refers to the symbol macro!
The macro expander knows about dwim and its semantics, and so it considers the possibility that localfun refers to the function and variable namespace. The closest lexical binding in either namespace is the flet and so the symbol macro expansion is suppressed (shadowed).
The dwim semantics is implicitly used in the partial evaluating op macro and its "cousins" derived from it.
Range Extraction task from Rosetta Code:
(defun range-extract (numbers)
`#{(mapcar [iff [callf > length (ret 2)]
(ret `#[#1 0]-#[#1 -1]`)
(ret `#{#1 ","}`)]
(mapcar (op mapcar car)
(split [window-map 1 :reflect
(op list #2 (- #2 #1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)
Y Combinator:
;; The Y combinator:
(defun y (f)
[(op #1 #1)
(op f (op [##1 ##1]))])
;; The Y-combinator-based factorial:
(defun fac (f)
(do if (zerop #1)
1
(* #1 [f (- #1 1)])))
;; Test:
(format t "~s\n" [[y fac] 4])
Moreover, various useful things are function callable in TXR Lisp. For instance, every sequence (list, vector or character string) is regarded as a function which maps numeric indices to elements. Thus we can do:
(mapcar "abc" #(2 1 0)) -> #(#\c #\b #\a)
The accepted answer describes a Racket mechanism for treating structures as functions. TXR has this in the form of lambda methods. This is demonstrated in the "OOP-Based" solution to the Accumulator Factory task in Rosetta:
(defstruct (accum count) nil
(count 0))
(defmeth accum lambda (self : (delta 1))
(inc self.count delta))
We can instantiate a (new (accum 9)) which will produce the values 10, 11, 12, ... when invoked as a function. An optional delta argument can be supplied for an increment other than 1:
(let ((acc (new (accum 0))))
(list [acc 5] [acc 5] [acc])) -> (5 10 11)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
What's the equivalence in scheme for the following code?
if (condition)
{
function1;
function2;
}
else
{
function3;
function4;
}
Thanks.
The parallel code where the code executes a block for each of the true and false branches is:
(if (condition)
(begin
(function1)
(function2))
(begin
(function3)
(function4)))
It depends. You really should try to narrow you question further with an actual problem in scheme since the answer will depend on what you are trying to do.
In idiomatic Scheme most should be done without side effects so you have
(if predicate-expression
consequent-expression
alternative-expression) ;; alternative is optional but should be used anyway.
But with your code you have more than one thing in the branches, something like:
int test (condition)
{
if (condition)
{
function1();
return function2();
}
else
{
function3();
return function4();
}
}
Here, in order for function1 and function3 to do anything useful it has to mutate, read or write something, also called a side effect. You should try to avoid that so in Scheme you either use a let to store a temporary variable, do the call so when it returns it is used like this:
(define (test condition)
(if condition
(let ((tmp (function3)))
(function4 tmp))
(function4 (function3))))
Now. You will eventually need side effects for a few procedures and then you need to use begin or use cond which has explicit begin.
(if predicate-expression
(begin
consequent-side-effect-expression
consequent-tail-expression)
(begin
alternative-side-effect-expression
alternative-tail-expression))
Now begin joins together several expressions into one and the result of a begin block is it's last expression, thus you can even use it in the predicate. Cond has an explicit begin in every consequent so I often switch from if to cond when I either need more than one consequent or a begin:
(cond (predicate-expression consequent-side-effect-expression
consequent-tail-expression)
(predicate2-expression consequent2-tail-expression2)
(else alternative-side-effect-expression
alternative-tail-expression))
Often when there is side effects you not always need the alternative. Eg. you are actually not interested in what the if returns because it may not be in tail position either. In these cases you have in the (rnrs control (6)) library when and unless with explicit begin:
(when expression
consequent-side-effect-expression
...
consequent-tail-expression)
(unless expression
consequent-side-effect-expression
...
consequent-tail-expression)
A let or a procedure also has explicit begin:
(let ()
(display "hello") ; displays "hello"
5) ; returns 5
(define (test x)
(display x) ; display x
(+ x 5)) ; return x+5
How about
(if condition
then-code
else-code)
Scheme also has the more general
(cond
((test1) case-1)
((test2) case-2)
...
(else else-case))
If you are using Racket, then
(when test then-code)
is if without the else.
There are a few Intro to Scheme sites that cover this sort of thing. Here's an example from the link included:
(define (min a b)
(if (< a b)
a
b))
WorBlux replied in another thread:
(if condition1 (begin function1 function2) (begin function3
function4)) 'begin' is a procedure/macro that forces sequential
evaluation of each of its arguments from left to right, and returns
the value of the last argument evaluated. In the cond form each clause
is wrapped in an implicit begin. Also the define special form is also
so wrapped, so you can do (cond (condition1 function1 function2) (else
function3 function4)) – WorBlux
I trying to complete this exercise;
Write a Lisp function that takes as input a list of elements, such as (A B C)
, and returns a list in which the position of each element follows it, such as (A 1 B 2 C 3)
I'm trying to do it with two functions, however its not working correctly, I'm just getting the same list. Here is my code:
(defun insert (index var userList)
(if (or (eql userList nil) (eql index 1))
(cons var userList)
(cons (car userList) (insert (- index 1) var (cdr userList)))))
(defun insertIndex (userList)
(setq len (length userList))
(loop for x from 1 to len
do (insert x x userList)))
The insert functions seems to work fine on its own, but it seems like it doesn't do anything with loop. I'm new lisp and any help would be appreciated, thanks in advance.
Positions in Lisp start with 0. In insertIndex the variable len is not defined. The LOOP does not return any useful value.
If you want to solve it with recursion, the solution is much simpler.
You need to test for the end condition. If the list is empty, return the empty list.
Otherwise create a new list with the FIRST element, the current position and the result of calling the function on the rest of the list and the position increased by one.
(LIST* 1 2 '(3 4)) is shorter for (cons 1 (cons 2 '(3 4))).
Here is the example with a local function. To create a top-level function with DEFUN is now your task. You only need to rewrite the code a bit. LABELS introduces a potentially recursive local function.
(labels ((pos-list (list pos)
(if (null list)
'()
(list* (first list)
pos
(pos-list (rest list) (1+ pos))))))
(pos-list '(a b c d e f) 0))
The main problem with your insertIndex function is that the do clause of loop is for side-effects only, it doesn't change the return value of the loop. (And your insert is side-effect free.) The right loop clause to add elements to a list return value is collect. (There are also append and nconc to join multiple lists.)
This is a working function:
(defun insert-index (list)
(loop for elt in list and i from 1
collect elt
collect i))
Your whole expectations about the behaviour of the insert and insertIndex functions seem to be flawed. You need to get a clearer mental model about which functions are side-effecting, which are not, and whether you need side-effects or not to solve some particular problem.
Also, you shouldn't call setq on an undefined variable in Common Lisp. You need to first use let to introduce a new local variable.
Minor points: CamelCase is very unidiomatic in Lisp. The idiomatic way to seperate words in identifiers is to use dashes, like I did in my code example. And you don't need to do (eql something nil), there's the special null function to check if something's nil, e.g. (null something).