I'm trying to create multiple nested if statements in mit-scheme with a similar structure as:
(if (null? (x))
L
(if (< (x) (y))
.. do stuff .. )
(if (< (y) (z))
.. do stuff .. )
)
However, when I compile it, it gives me:
Ill-formed special form: (if (null? ...) l (if ... ... ...) (if ... ... ...))
Does anyone know what's causing this? I'm essentially trying to go: if this condition is true, check if these two conditions are also true and perform an action accordingly.
I'm compiling with:
mit-scheme --quiet --load program.scm
Related
I am new to common lisp and trying to get a list out of a splitted string.
For example:
["4-No 16dia","6-No 20dia"]
Now I want to collect only the third element like ["16","20"]
I have got the splitting part correctly using:
(defun my-split (string &key (delimiterp #'delimiterp)
)
(loop :for beg = (position-if-not delimiterp string)
:then (position-if-not delimiterp string :start (1+ end)
)
:for end = (and beg (position-if delimiterp string :start beg))
:when beg :collect (subseq string beg end)
:while end))
where :
(defun delimiterp (c) (position c " ,-:"))
but collecting only the third element into a list is the tricky part , I have tried:
(defparameter *list1*
(loop for i in (cdr list)
(append (parse-integer
(nth 0
(my-split (nth 3 i)
:delimiterp #'delimiterp))))))
P.S: there are two list cz the example string is itself part of a list-of lists
Please help me, thanks in advance
I would use a regular expression, and I think I would do this largely irrespective of the language that I was using. Of course, some languages don't have regular expressions, but when they do it saves reinventing the wheel.
In Common Lisp, the regular expressions library is called Common Lisp - Practical Perl Compatible Regular Expressions, cl-ppcre. We load this with (ql:quickload "cl-ppcre").
Then the numbers can be returned using (ppcre:scan-to-strings "^(\\d*)-No (\\d*)dia$" x). The regular expression uses \d to pick out a digit, which in Lisp strings is written \\d. The asterisk says return zero or more digits. The parentheses in the regular expression is the bits that we are going to return, the numbers.
Doing this for a list of string is then just using mapcar.
(defparameter text-match "")
(defparameter text-numbers "")
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(setf (values text-match text-numbers)
(ppcre:scan-to-strings "^(\\d*)-No (\\d*)dia$" text))
text-numbers)
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
Edit: lexical bindings
When I was writing the above, I was trying to get the regular expression right AND trying to get the lexical bindings right at the same time. Having only limited time I put the effort into getting the regular expressions right, and used dynamic variables and setf. OK, it got the job done, but we can do better.
The classical lexical binding system is let, syntax (let ( (var1 val1) (var2 val2) ...) body). We can try (let ((x 0))), which is valid Lisp code, but which doesn't do much. As soon as the lexical scope ends, the variable x is unbound. Attempting to access x causes an error.
We can return multiple values from many functions, such as floor or scan-to-string. We now have to bind these values to variables, using (multiple-value-bind (variable-list) values). Most websites don't really do a good job of explaining this. Having bound the variables, I was getting errors about unbound variables. OK, it's worth just saying -
multiple-value-bind binds variables lexically, just like let.
The full syntax is (multiple-value-bind (variable-list) values body) and your code goes into the body section, just like let. Hence the above code becomes:
(defparameter test-text '("4-No 16dia" "6-No 23dia"))
(defun extract-numbers (text)
(multiple-value-bind (text-match text-numbers)
(ppcre:scan-to-strings "^(\\d*)-No (\\d*)dia$" text)
text-numbers))
(defun extract-numbers-from-list (lst)
(mapcar #'extract-numbers lst))
(extract-numbers-from-list test-text) ; => (#("4" "16") #("6" "23"))
Just to add, cl-ppcre also has register-groups-bind to do regex matching, binding, and converting in a single form:
CL-USER> (cl-ppcre:register-groups-bind ((#'parse-integer no dia))
("(\\d+)-No (\\d+)dia" "4-No 16dia")
(values no dia))
4
16
Without dependencies, one could use:
(defun extract-nums (s)
(mapcar #'(lambda (x) (parse-integer x :junk-allowed t))
(ql-util:split-spaces s)))
And try it with:
(defparameter *s* (list "4-No 16dia" "6-No 20dia"))
(mapcar #'extract-nums *s*)
;; => ((4 16) (6 20))
parse-integer with the setting junk-allowed-p t helps with extracting integer numbers from the string a lot.
But yes, in real-life I would also just use cl-ppcre, e.g.
Mainly the functions cl-ppcre:split and cl-ppcre:scan-to-strings.
(ql:quickload :cl-ppcre)
(defun extract-nums (s)
(mapcar #'parse-integer (cl-ppcre:scan-to-strings "(\\d+)-No (\\d+)dia" s))
And from then on it is just
(second (map #'list (mapcar #'extract-nums *s*))
;; => (16 20)
Note: I am doing this for homework. I'm not looking for the algorithm to solve my problem, just trying to understand how Scheme works.
I'm new to scheme and trying to write a small program to find the smallest item in a list. The program is working in the since that it is finding the correct answer (so the logic is somewhat sound), but I only know this because an error is coming up that it's trying to treat my answer as a function and call it.
(DEFINE (startmin mylist)
(
(repeatmin (CAR mylist) (CDR mylist))
))
(DEFINE (repeatmin curmin mylist)
(
(IF (NULL? mylist) ;If the list is empty
;This is where I'm at a loss. I want a way for this value to be
;sent out once the list is empty
curmin ;return the current minimum
(IF (< curmin (CAR mylist)) ;if the current minimum is less than the head of the list
(repeatmin curmin (CDR mylist)) ;recurse with curmin
(repeatmin (CAR mylist) (CDR mylist)) ;otherwise recurse with the head of the list.
)
)
))
I'm really at a loss of how I get the value, once found, back out of the recursion as it keeps trying to treat the value as a function.
Your parentheses are off. If you write
((if ...))
it means that the result from if is a function that immediately should be called once the value is cmoputed. It seems like you are using parentheses as if they are blocks, like {} in C, but they are not. In fact (begin ...) is a block in Scheme. And of course a function, let and cond terms have implicit begin.. Thus
(define (func . args)
(begin
x
y))
Is the same as
(define (func . args)
x
y)
Also please format your code correctly. Indentation helps you read the code and the nesting. I really don't pay attention to the parentheses, just the position which is crucial. Choose an editor that does this for you. Eg. DrRacket is a nice one I use.
In clojure, is it possible to execute multiple expressions in a cond case, without do or let form. In Racket, one may do things as:
(cond
(> a 0) ((display a) (display (* a a))
(= a 0) ...
...
Another form that contains an implicit do is when, so “yes,” you could achieve this without do or let:
(cond
(> a 0) (when true
(println a)
(println (* a a))))
But, of course, that's contrived and the real answer to your question is “no.”
Each clause has a pair of forms: A test form and an expression form. You can't have multiple expression forms in a cond clause—you'd need to further wrap them in a single form such as do. They are referred to as expression forms because usually their value is of interest (in a purely functional context) because it is the value of the expression in the clause with the first truthy test that the entire cond form evaluates to.
But, if you are using cond as a way to achieve conditional side effects, perhaps do is a good reinforcement of the intent:
(cond
(> a 0) (do (println a)
(println (* a a))))
I'm trying to filter out a list based off of a predicate I wrote myself, but when I run the filter, I get
ERROR: Wrong value to apply: #f
The code of the predicate:
;;;Predicate for checking if a string is not empty or full of whitespaces
(define (notwhitespace? str)
(if (equal? str "") #F (
(call-with-current-continuation
(lambda (return)
(for-each
(lambda (c)
(if (not (char-whitespace? c)) #T #F))
(string->list str))
#F))
)
)
)
this is my implementation of the filter (it is in a let statement):
(updated-strlist(filter notwhitespace? strlist))
any ideas? thanks!
So (call-with-current-continuation ...) in your code is wrappen in extra parentheses which means that Scheme should take the result and run it as a procedure the moment it gets it.
Usually in a LISP evaluator apply is the procedure that runs procedures. eg.
(define (test) (display "hello"))
(define (get-proc) test)
((get-proc)) ; ==> undefined, displays "hello"
You code however tries to do this (#f) and since #f is not a procedure apply cannot run it as if it were one.
A comment on the rest there. If you are not using return you really shouldn't use call-with-current-continuation at all and for-each does sonething entirely different than you think. nowhitespace? will always evaluate to #f when you've fixed your problems because the last expression in the body of the continuation lambda is #f (the returned value).
I guess you are looking for something like:
;; needs to import (srfi :1)
(define (notwhitespace? str)
(every (lambda (x) (not (char-whitespace? x)))
(list->string str)))
;; needs to import (srfi :13)
(define (notwhitespace2? str)
(not (string-index str char-whitespace?)))
Don't write (#f), it should be #f.
I am trying to build a quick toc from an html content. (to make it short)
The code is dead simple:
(defn toc [content]
(doseq [i (take 5 (iterate inc 1))]
(let [h (str "h" i)]
(println ($ content h)))))
where content is the html content, and $ is a macro required from clojure-soup
While
($ content "h1")
works, and returns a list of all the tags.
Simple:
($ content (str "h" 1))
just won't make it whatever I do.
How do I force
(str "h" 1)
to be properly eval-ed before the macro is called ?
Bonus points for explaining why :)
This is not possible if, as you imply, $ is a macro: it's simply not how macros work. The macro needs to expand into something, at compile time, and it can only do so once. You have run-time data, like the various values of h, but there is no way to use that at compile-time. To me it sounds like $ should have been a function.
Amalloy answer the questions why part. For making it work part you will need to use eval .
In place of ($ content h) use
(eval `($ content ~h))
Another explanation for why this is so is based on the fact that what operations does the macro do at compile time and what it does at runtime (i.e what code it emits). Below is such an example to clear things out.
(def user "ankur")
(defmacro do-at-compile [v] (if (string? v) `true `false))
(defmacro do-at-runtime [v] `(if (string? ~v) true false))
(do-at-compile "hello") ;; => true
(do-at-compile user) ;; => false, because macro does perform the check at compile time
(do-at-runtime "hello") ;; => true
(do-at-runtime user) ;; => true
The $ macro is doing the calculations on the passed second parameter at compile time and hence it is not working in your particular case.