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
Related
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.
I am trying to construct a function "number-crop" which takes three arguments x a b. If x is to the left of the closed interval [a, b] on the number line, then return a. If x is to the right of the interval, then return b. Otherwise, just return x. This is what I have:
(define (number-crop x a b)
(if (max x a b) x b)
(if (min x a b) x a))
I am returned with the error, "define: expected only one expression for the function body, but found 1 extra part". I am new to Racket so I am still trying to understand how if statements work within the language.
Scheme/Racket if expressions always have exactly one condition and exactly two branches. Since they are expressions, not statements, this makes them very useful, and they function much like the conditional “ternary” operator in languages in the C family. However, when you have multiple conditions, you likely want something closer to if...else if chains, which is provided via the cond form.
The cond form is just like if, except with the ability to have any number of “clauses” which are each determined by a single condition. Using cond, your number-crop function would look like this:
(define (number-crop x a b)
(cond
[(< x a) a]
[(> x b) b]
[else x]))
(Note that else is special inside of cond—it replaces the condition for the last clause, and it always runs if the other cases fail.)
This would likely work, but if you already have access to min and max, you don’t actually need to branch at all! If you use those two functions together, you can write number-crop with neither if nor cond:
(define (number-crop x a b)
(min (max a x) b))
This works because composing both min and max will effectively clamp the value within the given range, provided that a is always the minimum and b is always the maximum.
In Scheme (Racket), functions are defined to return one thing. In your case it is clear: the result of the operation you describe. However, Scheme is different from most imperative languages in several respects. For example, if you look at your expression inside the define, it contains two expressions, one after the other. This contradicts the "one expression that calculates the function" assumption in Scheme.
Moreover, even if you write it in an imperative language, you'd use nested ifs, that you can of course use here. Something along the lines of:
(define (number-crop x a b)
(if (= x (max x a b))
b
(if (= x (min x a b))
a
x)))
I need to write a function in lisp with two arguments - list of argumentless functions and list of integers.
I need to evaluate functions from first list in order given by a second, i.e. (fun '(#'a #'b #'c) '(2 0 1)) should evaluate c, a, b.
I tried such function:
(defun z4(funs kols)
(funcall (nth (first kols) funs))
(z4 funs (rest kols))
)
but in funcall I am geting error
NIL is not of type CONS.
What does it means? I am getting same error by calling simply
(funcall (first funs))
so I assume it is something with with getting function from the list of functions. How can I evaluate function get from list of functions?
With each recursive call you reduce the kols parameter untill it becomes nil. When kols becomes nil you should terminate the recursion, so you should add the test for the terminating condition (i.e., for empty list):
(defun foo (funcs order)
(unless (endp order)
(funcall (nth (first order) funcs))
(foo funcs (rest order))))
I suggest a more readable solution (it's also more preferrable since ANSI Common Lisp Standard doesn't force implementations to perform tail call optimization):
(defun foo (funcs order)
(loop for n in order do (funcall (nth n funcs))))
In the previous examples I assume that you run your functions for their side effects, not for the return values.
Edit 1
As Vatine noted, using nth and lists to provide a collection with random access is not good for the performance, so it might be worth to store functions in a vector (that is a one-dimensional array) rathen than in a list. So, assuming that funcs is a vector of functions, the function can be defined as follows:
(defun foo (funcs order)
(loop for n in order do (funcall (aref funcs n))))
Moreover, we can replace aref with svref if the array of functions is a simple vector (glossary entry). The former is more general, but the latter may be faster in some implementations.
One can create a simple vector of functions using either
(vector #'func-a #'func-b ...)
or
#(func-a func-b ...)
A simple vector of functions can be created using the make-array function as well, but only if :adjustable and :fill-pointer keyword arguments are unspecified or nil.
'(#'a #'b #'c)
is not a list of functions A, B, C. It is this:
((FUNCTION A) (FUNCTION B) (FUNCTION C))
Above are not functions, but lists with the first symbol FUNCTION and then another symbol.
Use either
(list #'a #'b #'c)
or
'(a b c)
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).
If I have something like this:
int foo() {
if(somecondition) {
// some code
if(cond2) return -1;
// some code again
}
if(cond3){
// something again
}
return bar();
}
How do I express it in Clojure?
it should not be written as if_elseif because both the somecondition and cond3 may be true and both may be execute.
From the suggestions below, I am suggesting one more solution. Please let me know if that is right or not:
(defn foo []
(if (somecondition)
( (some-code) (if (cond2) -1 (some-code-again)) )
1 ; empty statement
)
(if (cond3) (something-again) 1)
(bar))
You could argue that this is bad style since it's hard to understand the flow of control unless of course this pattern is being used to return error conditions (which is common in C). Clojure supports exceptions. If you really want to send control elsewhere use them.
You can undo the knots in the flow of control by refactoring some of the code out into a separate function; this will work in C and in Clojure too.
Here's my stab at it. Hand translated and not tested, so it could be buggy.
(defn foo []
(let [foo2 (fn []
(if cond3 "something again")
(bar))]
(if somecondition
(do
"some code"
(if cond2
-1
(do
"some code again"
(foo2))))
(foo2))))
UPDATE with some explanation.
Because ajay asked, I'd like to expose a little of the thinking that led me to the above solution.
; shortcuts
c1 = somecondition
c2 = cond2
c3 = cond3
; truth table (this helped me a bit with my thinking but didn't go directly into the design)
c1 c2 c3 results
----------------
T T . "some code" -1
T F T "some code" "some code again" "something again" bar()
T F F "some code" "some code again" bar()
F . T "something again" bar()
F . F bar()
The way Clojure works, there's no "return". A Clojure function always returns the last expression to be evaluated. If we want to produce the same side effects (from "some code", "some code again" and "something again") and result as the C/Java code, we need to make the code run in such a way that the result is really the last thing executed.
The only way to be able to return -1 is to rework the code so there is a branch from the start that ends - really ends - at "-1". That means that the following code must be called from within one of the other IF branches. In fact, it appears in two branches. So as not to have to repeat the code, I pulled it into a function of its own.
Here's the translation of my code to pseudocode:
function foo2:
if c3 then
"something again"
endif
bar()
function foo:
if c1 then
"some code"
if c2 then
-1 <-- end 1
else
"some code again"
foo2 <-- end 2
endif
else
foo2 <-- end 3
endif
end 1 is your tricky "return -1". end 2 includes "some code again", end 3 doesn't. Both end 2 and end 3 test c3, maybe do "something again" and then return bar().
I think it would look something like this:
(defn foo
[]
(if somecondition
(do
; some code
(if cond2
-1
(do
; somecode again
(if cond3
(do
; something again))
(bar))))
(do
(if cond3
(do
; something again))
(bar))))
How ugly - don't do that :)
As far as I know the lack of control jumps is by design. This function is entirely side-effect driven which is a red flag that maybe the underlying problem may be better represented in another way, but it is hard to give any real advice as the example is entirely abstract. CL has a return-from which is rarely used "because all Lisp expressions, including control constructs such as loops and conditionals, evaluate to a value". There is no return-from in Clojure.
Lets start off with some literal translations to establish a common ground:
int foo() {
(defn foo []
if(somecondition) {
(if somecondition
// some code
(some-code 1 2 3)
if(cond2) return -1;
(if cond2
-1
// some code again
(some-code 1 2 3)
}
if(cond3){
// something again
}
(if cond3
(something :again)
return bar();
(bar)))))
}
We have to adjust this to make it what could be described at "all one big long return statement" or as people that really dig functional programming call it "a function".
(defn helper-function []
(if cond3
(something again))
bar))
(defn foo []
(if somecondition
(some-code 1 2 3)
(if cond2
-1
(helper-function)
(helper-function)
The function has two places where the return point is determined. in clojure this is just the ends of the function. A clojure function returns the result of the last expression evaluated before the function is over otherwise we would be writing return everywhere. (helper-function) had to be called twice because there are two code paths that use it.
That code example is ready made for when
(defn foo []
(when somecondition
; code goes here
(do-somecondition-code)
(when cond2
; more code goes here
(do-cond2-code)))
(when cond3
; even more code here
(do-cond3-code))
(bar))
The code is clear readable and concise and does exactly what you specified.
First I defined some helper functions to verify when the functions are being called.
(defn some-code [] (println "some code"))
(defn some-code-again [] (println "some code again"))
(defn something-again [] (println "something again"))
(defn bar [] "bar")
Then I defined foo like this accepting the three conditionals so I could test it:
(defn foo [somecondition cond2 cond3]
(if (and somecondition cond2)
(do (when somecondition (some-code)) -1)
(do
(when somecondition (some-code))
(when cond3 (something-again))
(bar))))
I took couple of liberties. First, the C code might allow cond2 to be set in some code which could be handled as well with a let statement. Also, I wouldn't normally have the do clauses but since I have no idea what the code really does, it is not possible to make meaningful function names.
Another style note: In C it is usually bad style to have multiple return statements in a function. Another bonus of converting to a functional style forced the paths through the code to become clearer.
EDIT: I verified this code with
(for [somecondition [true false] cond2 [true false] cond3 [true false] ]
(do
(println "========")
(println "round" somecondition cond2 cond3)
(println "result:" (foo somecondition cond2 cond3))))
Ignore the nils that showup, they are because println returns nil